<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Responses\ApiResponse;
use App\Models\ConfigGroup;
use App\Models\ConfigItem;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;

class ConfigItemController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        try {
            $query = ConfigItem::with('group');

            if ($request->filled('group_id')) {
                $query->where('group_id', $request->input('group_id'));
            }

            if ($request->filled('keyword')) {
                $keyword = $request->input('keyword');
                $query->where(function ($q) use ($keyword) {
                    $q->where('name', 'like', "%{$keyword}%")
                        ->orWhere('code', 'like', "%{$keyword}%");
                });
            }

            $items = $query->orderBy('sort', 'asc')->orderBy('id', 'asc')->get();

            return response()->json(ApiResponse::success($items));
        } catch (\Exception $e) {
            return response()->json(ApiResponse::error(50001, '获取配置项失败：'.$e->getMessage()));
        }
    }

    public function store(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'group_id' => 'required|integer|exists:config_groups,id',
                'name' => 'required|string|max:50',
                'code' => 'required|string|max:50|unique:config_items,code',
                'type' => 'required|string|in:text,number,switch,select,textarea,image,password',
                'value' => 'nullable|string',
                'options' => 'nullable|array',
                'tips' => 'nullable|string|max:255',
                'sort' => 'nullable|integer',
            ]);

            $item = ConfigItem::create([
                'group_id' => $request->input('group_id'),
                'name' => $request->input('name'),
                'code' => $request->input('code'),
                'type' => $request->input('type'),
                'value' => $request->input('value', ''),
                'options' => $request->input('options'),
                'tips' => $request->input('tips'),
                'sort' => $request->input('sort', 0),
                'status' => 1,
            ]);

            return response()->json(ApiResponse::success($item, '创建配置项成功'));
        } catch (\Exception $e) {
            return response()->json(ApiResponse::error(50001, '创建配置项失败：'.$e->getMessage()));
        }
    }

    public function update(Request $request, int $id): JsonResponse
    {
        try {
            $item = ConfigItem::find($id);

            if (! $item) {
                return response()->json(ApiResponse::error(40302, '配置项不存在'));
            }

            $group = ConfigGroup::find($item->group_id);
            $isSystem = $group && in_array($group->code, self::SYSTEM_CONFIG_CODES);

            $rules = [
                'name' => 'nullable|string|max:50',
                'value' => 'nullable|string',
                'options' => 'nullable|array',
                'tips' => 'nullable|string|max:255',
                'sort' => 'nullable|integer',
            ];
            if (!$isSystem) {
                $rules['group_id'] = 'nullable|integer|exists:config_groups,id';
                $rules['code'] = 'nullable|string|max:50|unique:config_items,code,'.$id;
                $rules['type'] = 'nullable|string|in:text,number,switch,select,textarea,image,password';
            }
            $request->validate($rules);

            $updateData = array_filter([
                'name' => $request->input('name'),
                'value' => $request->input('value'),
                'options' => $request->input('options'),
                'tips' => $request->input('tips'),
                'sort' => $request->input('sort'),
            ], function ($v, $k) {
                return $v !== null || in_array($k, ['value', 'options', 'tips']);
            }, ARRAY_FILTER_USE_BOTH);

            if (!$isSystem) {
                $nonSystemData = array_filter([
                    'group_id' => $request->input('group_id'),
                    'code' => $request->input('code'),
                    'type' => $request->input('type'),
                ], fn ($v) => $v !== null);
                $updateData = array_merge($updateData, $nonSystemData);
            }

            $item->update($updateData);

            return response()->json(ApiResponse::success($item, '更新配置项成功'));
        } catch (\Exception $e) {
            return response()->json(ApiResponse::error(50001, '更新配置项失败：'.$e->getMessage()));
        }
    }

    protected const SYSTEM_CONFIG_CODES = ['basic', 'upload', 'security', 'email'];

    public function destroy(int $id): JsonResponse
    {
        try {
            $item = ConfigItem::find($id);

            if (! $item) {
                return response()->json(ApiResponse::error(40302, '配置项不存在'));
            }

            $group = ConfigGroup::find($item->group_id);
            if ($group && in_array($group->code, self::SYSTEM_CONFIG_CODES)) {
                return response()->json(ApiResponse::error(40303, '系统内置配置项不允许删除'));
            }

            $item->delete();

            return response()->json(ApiResponse::success(null, '删除配置项成功'));
        } catch (\Exception $e) {
            return response()->json(ApiResponse::error(50001, '删除配置项失败：'.$e->getMessage()));
        }
    }

    public function batch(Request $request): JsonResponse
    {
        try {
            $items = $request->input('items', []);

            if (empty($items)) {
                return response()->json(ApiResponse::error(40201, '没有需要更新的配置'));
            }

            DB::beginTransaction();
            foreach ($items as $data) {
                if (! isset($data['id'])) {
                    continue;
                }

                ConfigItem::where('id', $data['id'])->update([
                    'value' => $data['value'] ?? '',
                ]);
            }
            DB::commit();

            Artisan::call('config:clear');

            return response()->json(ApiResponse::success(null, '保存配置成功'));
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(ApiResponse::error(50001, '批量更新失败：'.$e->getMessage()));
        }
    }
}
