<?php

namespace Kylin\Settings\Models;

use Illuminate\Support\Facades\Cache;
use Kylin\Core\Models\BaseModel;

/**
 * 系统设置模型
 *
 * 键值对形式的系统配置存储，支持分组和类型转换。
 *
 * @property string $group       分组
 * @property string $key         键名
 * @property string $value       值
 * @property string $type        值类型
 * @property string $description 描述
 */
class Setting extends BaseModel
{
    protected $table = 'kylin_settings';

    protected $fillable = ['group', 'key', 'value', 'type', 'description'];

    protected $casts = [
        'value' => 'string',
    ];

    public static function getValue(string $key, mixed $default = null, string $group = 'default'): mixed
    {
        $cacheKey = config('kylin-settings.cache.key', 'kylin.settings') . ".{$group}.{$key}";
        $ttl = config('kylin-settings.cache.ttl', 3600);

        if (config('kylin-settings.cache.enabled', true)) {
            return Cache::remember($cacheKey, $ttl, function () use ($key, $default, $group) {
                return static::queryValue($key, $default, $group);
            });
        }

        return static::queryValue($key, $default, $group);
    }

    public static function setValue(string $key, mixed $value, string $type = 'string', string $group = 'default', ?string $description = null): self
    {
        $setting = static::updateOrCreate(
            ['group' => $group, 'key' => $key],
            ['value' => is_array($value) ? json_encode($value) : (string) $value, 'type' => $type, 'description' => $description],
        );

        $cacheKey = config('kylin-settings.cache.key', 'kylin.settings') . ".{$group}.{$key}";
        Cache::forget($cacheKey);

        return $setting;
    }

    private static function queryValue(string $key, mixed $default, string $group): mixed
    {
        $setting = static::where('group', $group)->where('key', $key)->first();
        if ($setting === null) {
            return $default;
        }
        return match ($setting->type) {
            'int', 'integer' => (int) $setting->value,
            'bool', 'boolean' => filter_var($setting->value, FILTER_VALIDATE_BOOLEAN),
            'json', 'array' => json_decode($setting->value, true),
            'float' => (float) $setting->value,
            default => $setting->value,
        };
    }
}
