<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;

class Setting extends Model
{
    protected $table = 'settings';
    protected $primaryKey = 'key'; // Laravel5 behavior - string primary key
    public $incrementing = false; // Not auto-incrementing
    protected $keyType = 'string'; // String primary key
    public $timestamps = false; // Laravel5 behavior - no timestamps
    protected $fillable = ['key', 'value'];

    /**
     * Get a setting value by key
     *
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    public static function get($key, $default = null)
    {
        $cacheKey = "setting_{$key}";
        
        return Cache::remember($cacheKey, 86400, function () use ($key, $default) { // 24 hours instead of 1 hour
            $setting = static::where('key', $key)->first();
            
            if (!$setting) {
                return $default;
            }
            
            return static::castValue($setting->value);
        });
    }

    /**
     * Set a setting value
     *
     * @param string $key
     * @param mixed $value
     * @return bool
     */
    public static function set($key, $value)
    {
        $serializedValue = static::serializeValue($value);
        
        // Use Laravel5 style - find or create with string primary key
        $setting = static::find($key);
        if ($setting) {
            $setting->value = $serializedValue;
            $result = $setting->save();
        } else {
            $setting = new static();
            $setting->key = $key;
            $setting->value = $serializedValue;
            $result = $setting->save();
        }
        
        // Clear cache
        Cache::forget("setting_{$key}");
        
        return $result;
    }

    /**
     * Store a setting value (alias for set)
     *
     * @param string $key
     * @param mixed $value
     * @return bool
     */
    public static function store($key, $value)
    {
        return static::set($key, $value);
    }

    /**
     * Delete a setting by key
     *
     * @param string $key
     * @return bool
     */
    public static function deleteKey($key)
    {
        $deleted = static::where('key', $key)->delete();
        if ($deleted) {
            Cache::forget("setting_{$key}");
        }
        return $deleted;
    }

    /**
     * Clear all settings cache
     */
    public static function clear()
    {
        $settings = static::all();
        
        foreach ($settings as $setting) {
            Cache::forget("setting_{$setting->key}");
        }
    }

    /**
     * Get settings by group (e.g., 'emails', 'ldap')
     *
     * @param string $group
     * @return array
     */
    public static function getGroup($group)
    {
        $settings = static::where('key', 'like', $group . '.%')->get();
        $result = [];
        
        foreach ($settings as $setting) {
            $key = str_replace($group . '.', '', $setting->key);
            $result[$key] = static::castValue($setting->value);
        }
        
        return $result;
    }

    /**
     * Cast value based on intelligent type detection
     *
     * @param mixed $value
     * @return mixed
     */
    protected static function castValue($value)
    {
        // Handle null and empty values
        if ($value === null || $value === '') {
            return $value;
        }

        // Try to decode JSON first
        $decoded = json_decode($value, true);
        if (json_last_error() === JSON_ERROR_NONE) {
            return $decoded;
        }

        // Handle boolean strings
        if (in_array(strtolower($value), ['true', '1', 'yes', 'on'])) {
            return true;
        }
        if (in_array(strtolower($value), ['false', '0', 'no', 'off'])) {
            return false;
        }

        // Handle numeric values
        if (is_numeric($value)) {
            return strpos($value, '.') !== false ? (float) $value : (int) $value;
        }

        // Return as string
        return $value;
    }

    /**
     * Serialize value for storage
     *
     * @param mixed $value
     * @return string
     */
    protected static function serializeValue($value)
    {
        if (is_array($value) || is_object($value)) {
            return json_encode($value);
        }
        
        if (is_bool($value)) {
            return $value ? '1' : '0';
        }
        
        return (string) $value;
    }
} 