<?php

namespace App\Services\System;

use App\Models\System\Config;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Validator;

class ConfigService
{
    public function getList(array $params): array
    {
        $query = Config::query();

        if (!empty($params['group'])) {
            $query->where('group', $params['group']);
        }

        if (!empty($params['keyword'])) {
            $query->where(function ($q) use ($params) {
                $q->where('name', 'like', '%' . $params['keyword'] . '%')
                    ->orWhere('key', 'like', '%' . $params['keyword'] . '%');
            });
        }

        if (isset($params['status']) && $params['status'] !== '') {
            $query->where('status', $params['status']);
        }

        $pageSize = $params['page_size'] ?? 20;
        $list = $query->orderBy('sort')->orderBy('id')->paginate($pageSize);

        return [
            'list' => $list->items(),
            'total' => $list->total(),
            'page' => $list->currentPage(),
            'page_size' => $list->perPage(),
        ];
    }

    public function getById(int $id): ?Config
    {
        return Config::find($id);
    }

    public function getByKey(string $key): ?Config
    {
        return Config::where('key', $key)->first();
    }

    public function getByGroup(string $group): array
    {
        return Config::where('group', $group)
            ->where('status', true)
            ->orderBy('sort')
            ->get()
            ->toArray();
    }

    public function getAllConfig(): array
    {
        $cacheKey = 'system:configs:all';
        $configs = Cache::get($cacheKey);

        if ($configs === null) {
            $configs = Config::where('status', true)
                ->orderBy('sort')
                ->get()
                ->keyBy('key')
                ->toArray();
            Cache::put($cacheKey, $configs, 3600);
        }

        return $configs;
    }

    public function getConfigValue(string $key, $default = null)
    {
        $config = $this->getByKey($key);
        if (!$config) {
            return $default;
        }

        return $config->value ?? $config->default_value ?? $default;
    }

    public function create(array $data): Config
    {
        Validator::make($data, [
            'group' => 'required|string|max:50',
            'key' => 'required|string|max:100|unique:system_setting,key',
            'name' => 'required|string|max:100',
            'type' => 'required|string|in:string,text,number,boolean,select,radio,checkbox,file,json',
        ])->validate();

        $config = Config::create($data);
        $this->clearCache();
        return $config;
    }

    public function update(int $id, array $data): Config
    {
        $config = Config::findOrFail($id);

        Validator::make($data, [
            'group' => 'sometimes|required|string|max:50',
            'key' => 'sometimes|required|string|max:100|unique:system_setting,key,' . $id,
            'name' => 'sometimes|required|string|max:100',
            'type' => 'sometimes|required|string|in:string,text,number,boolean,select,radio,checkbox,file,json',
        ])->validate();

        $config->update($data);
        $this->clearCache();
        return $config;
    }

    public function delete(int $id): bool
    {
        $config = Config::findOrFail($id);

        if ($config->is_system) {
            throw new \Exception('系统配置不能删除');
        }

        $config->delete();
        $this->clearCache();
        return true;
    }

    public function batchDelete(array $ids): bool
    {
        $configs = Config::whereIn('id', $ids)->where('is_system', false)->get();
        Config::whereIn('id', $configs->pluck('id'))->delete();
        $this->clearCache();
        return true;
    }

    public function batchUpdateStatus(array $ids, bool $status): bool
    {
        Config::whereIn('id', $ids)->update(['status' => $status]);
        $this->clearCache();
        return true;
    }

    private function clearCache(): void
    {
        Cache::forget('system:configs:all');
    }

    public function getGroups(): array
    {
        return Config::where('status', true)
            ->select('group')
            ->distinct()
            ->pluck('group')
            ->toArray();
    }
}
