<?php

/**
 * 文件功能：AI 厂商配置管理控制器（管理后台）
 *
 * 提供完整的 AI 厂商 CRUD 管理功能，包括：
 * - 列表/新增/编辑/删除 AI 厂商配置
 * - 切换启用/禁用状态
 * - 设置默认厂商（互斥，同时只有一个默认）
 * - 全局开关控制机器人是否启用
 *
 * @author   ChatRoom Laravel
 *
 * @version  1.0.0
 */

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\AiProviderConfig;
use App\Models\Sysparam;
use App\Services\ChatStateService;
use App\Services\ChatUserPresenceService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\View\View;

class AiProviderController extends Controller
{
    /**
     * 构造函数
     */
    public function __construct(
        private readonly ChatStateService $chatState,
        private readonly ChatUserPresenceService $chatUserPresenceService,
    ) {}

    /**
     * 显示 AI 厂商配置列表页面
     *
     * 列出所有已配置的 AI 厂商，并显示全局开关状态。
     *
     * @return View AI 厂商管理页面
     */
    public function index(): View
    {
        $providers = AiProviderConfig::orderBy('sort_order')->get();
        $chatbotEnabled = Sysparam::getValue('chatbot_enabled', '0') === '1';
        $chatbotMaxGold = Sysparam::getValue('chatbot_max_gold', '5000');
        $chatbotMaxDailyRewards = Sysparam::getValue('chatbot_max_daily_rewards', '1');
        $chatbotFishingEnabled = Sysparam::getValue('chatbot_fishing_enabled', '0') === '1';
        $chatbotFishingChance = Sysparam::getValue('chatbot_fishing_chance', '5');
        $chatbotBaccaratEnabled = Sysparam::getValue('chatbot_baccarat_enabled', '0') === '1';

        return view('admin.ai-providers.index', compact(
            'providers', 'chatbotEnabled', 'chatbotMaxGold',
            'chatbotMaxDailyRewards', 'chatbotFishingEnabled', 'chatbotFishingChance', 'chatbotBaccaratEnabled'
        ));
    }

    /**
     * 保存全局设置
     */
    public function updateSettings(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'chatbot_max_gold' => 'required|integer|min:1',
            'chatbot_max_daily_rewards' => 'required|integer|min:1',
            'chatbot_fishing_enabled' => 'required|in:0,1',
            'chatbot_fishing_chance' => 'required|integer|min:1|max:100',
            'chatbot_baccarat_enabled' => 'required|in:0,1',
        ]);
        Sysparam::updateOrCreate(
            ['alias' => 'chatbot_max_gold'],
            [
                'body' => (string) $data['chatbot_max_gold'],
                'guidetxt' => '单次最高发放金币金额',
            ]
        );
        Sysparam::clearCache('chatbot_max_gold');

        Sysparam::updateOrCreate(
            ['alias' => 'chatbot_max_daily_rewards'],
            [
                'body' => (string) $data['chatbot_max_daily_rewards'],
                'guidetxt' => '每个用户单日最多获得金币次数',
            ]
        );
        Sysparam::clearCache('chatbot_max_daily_rewards');

        Sysparam::updateOrCreate(
            ['alias' => 'chatbot_fishing_enabled'],
            [
                'body' => $data['chatbot_fishing_enabled'],
                'guidetxt' => 'AI 参与钓鱼游戏开关',
            ]
        );
        Sysparam::clearCache('chatbot_fishing_enabled');

        Sysparam::updateOrCreate(
            ['alias' => 'chatbot_fishing_chance'],
            [
                'body' => (string) $data['chatbot_fishing_chance'],
                'guidetxt' => 'AI 钓鱼抛竿概率 (每分钟)',
            ]
        );
        Sysparam::clearCache('chatbot_fishing_chance');

        Sysparam::updateOrCreate(
            ['alias' => 'chatbot_baccarat_enabled'],
            [
                'body' => $data['chatbot_baccarat_enabled'],
                'guidetxt' => 'AI 参与百家乐游戏开关',
            ]
        );
        Sysparam::clearCache('chatbot_baccarat_enabled');

        return back()->with('success', '全局设置保存成功！');
    }

    /**
     * 新增 AI 厂商配置
     *
     * @param  Request  $request  请求对象
     * @return RedirectResponse 重定向到列表页
     */
    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'provider' => 'required|string|max:50',
            'name' => 'required|string|max:100',
            'api_key' => 'required|string',
            'api_endpoint' => 'required|url|max:255',
            'model' => 'required|string|max:100',
            'temperature' => 'nullable|numeric|min:0|max:2',
            'max_tokens' => 'nullable|integer|min:100|max:32000',
            'sort_order' => 'nullable|integer|min:0',
        ]);

        // 加密 API Key
        $data['api_key'] = Crypt::encryptString($data['api_key']);
        $data['temperature'] = $data['temperature'] ?? 0.3;
        $data['max_tokens'] = $data['max_tokens'] ?? 2048;
        $data['sort_order'] = $data['sort_order'] ?? 0;
        $data['is_enabled'] = true;
        $data['is_default'] = false;

        AiProviderConfig::create($data);

        return redirect()->route('admin.ai-providers.index')
            ->with('success', '已成功添加 AI 厂商配置！');
    }

    /**
     * 更新 AI 厂商配置
     *
     * @param  Request  $request  请求对象
     * @param  int  $id  厂商配置 ID
     * @return RedirectResponse 重定向到列表页
     */
    public function update(Request $request, int $id): RedirectResponse
    {
        $provider = AiProviderConfig::findOrFail($id);

        $data = $request->validate([
            'provider' => 'required|string|max:50',
            'name' => 'required|string|max:100',
            'api_key' => 'nullable|string',
            'api_endpoint' => 'required|url|max:255',
            'model' => 'required|string|max:100',
            'temperature' => 'nullable|numeric|min:0|max:2',
            'max_tokens' => 'nullable|integer|min:100|max:32000',
            'sort_order' => 'nullable|integer|min:0',
        ]);

        // 只在用户提供了新 API Key 时才更新（空值表示不修改）
        if (! empty($data['api_key'])) {
            $data['api_key'] = Crypt::encryptString($data['api_key']);
        } else {
            unset($data['api_key']);
        }

        $provider->update($data);

        return redirect()->route('admin.ai-providers.index')
            ->with('success', "已更新 {$provider->name} 的配置！");
    }

    /**
     * 切换 AI 厂商的启用/禁用状态
     *
     * @param  int  $id  厂商配置 ID
     * @return JsonResponse 操作结果
     */
    public function toggleEnabled(int $id): JsonResponse
    {
        $provider = AiProviderConfig::findOrFail($id);
        $provider->is_enabled = ! $provider->is_enabled;
        $provider->save();

        $status = $provider->is_enabled ? '启用' : '禁用';

        return response()->json([
            'status' => 'success',
            'message' => "{$provider->name} 已{$status}",
            'is_enabled' => $provider->is_enabled,
        ]);
    }

    /**
     * 设置指定厂商为默认使用
     *
     * 互斥操作：将其他厂商的 is_default 全部置为 false。
     *
     * @param  int  $id  厂商配置 ID
     * @return JsonResponse 操作结果
     */
    public function setDefault(int $id): JsonResponse
    {
        $provider = AiProviderConfig::findOrFail($id);

        // 先将所有厂商的默认标记清除
        AiProviderConfig::where('is_default', true)->update(['is_default' => false]);

        // 设置当前厂商为默认
        $provider->is_default = true;
        $provider->is_enabled = true; // 默认的必须是启用状态
        $provider->save();

        return response()->json([
            'status' => 'success',
            'message' => "{$provider->name} 已设为默认 AI 厂商",
        ]);
    }

    /**
     * 切换聊天机器人全局开关
     *
     * 通过 sysparam 的 chatbot_enabled 参数控制是否在聊天室中显示 AI 机器人。
     *
     * @param  Request  $request  请求对象
     * @return JsonResponse 操作结果
     */
    public function toggleChatBot(Request $request): JsonResponse
    {
        $current = Sysparam::getValue('chatbot_enabled', '0');
        $newValue = $current === '1' ? '0' : '1';

        // 更新 sysparam
        Sysparam::updateOrCreate(
            ['alias' => 'chatbot_enabled'],
            [
                'body' => $newValue,
                'guidetxt' => 'AI聊天机器人开关（1=开启，0=关闭）',
            ]
        );

        // 刷新缓存
        $this->chatState->setSysParam('chatbot_enabled', $newValue);
        Sysparam::clearCache('chatbot_enabled');

        $status = $newValue === '1' ? '开启' : '关闭';
        $isEnabled = $newValue === '1';

        // 确保 AI 实体账号存在
        $user = \App\Models\User::firstOrCreate(
            ['username' => 'AI小班长'],
            [
                'password' => \Illuminate\Support\Facades\Hash::make(\Illuminate\Support\Str::random(16)),
                'user_level' => 10,
                'sex' => 0, // 女性
                'usersf' => 'storage/avatars/ai_bot_cn_girl.png',
                'jjb' => 1000000,
                'sign' => '本群首席智慧小管家',
            ]
        );

        // 防止后期头像变动，强制更新到最新女生头像
        if (! str_contains($user->usersf ?? '', 'ai_bot_cn_girl.png')) {
            $user->update([
                'usersf' => 'storage/avatars/ai_bot_cn_girl.png',
                'sex' => 0,
            ]);
        }

        // 机器人在线载荷也统一走聊天室展示服务，避免名单字段口径逐步漂移。
        $userData = $this->chatUserPresenceService->build($user);

        // 广播机器人进出事件（供前端名单增删）
        broadcast(new \App\Events\ChatBotToggled($userData, $isEnabled));

        // 像真实的玩家一样，对全网活跃房间进行高调进出场播报
        $activeRoomIds = $this->chatState->getAllActiveRoomIds();
        if (empty($activeRoomIds)) {
            $activeRoomIds = [1]; // 兜底
        }

        // 把 AI 实体挂名到一个主房间，即可被 app/Console/Commands/AutoSaveExp.php 扫描发经验
        $mainRoomId = $activeRoomIds[0];
        if ($isEnabled) {
            $this->chatState->userJoin($mainRoomId, $user->username, $userData);
        } else {
            // 清理可能存在的所有房间的残留挂名
            foreach ($activeRoomIds as $rId) {
                $this->chatState->userLeave($rId, $user->username);
            }
        }

        foreach ($activeRoomIds as $roomId) {
            $content = $isEnabled
                ? '<span style="color: #9333ea; font-weight: bold;">🤖 【AI小班长】 迈着整齐的步伐进入了房间，随时为您服务！</span>'
                : '<span style="color: #9ca3af; font-weight: bold;">🤖 【AI小班长】 去休息啦，大家聊得开心！</span>';

            $botMsg = [
                'id' => $this->chatState->nextMessageId($roomId),
                'room_id' => $roomId,
                'from_user' => '进出播报',
                'to_user' => '大家',
                'content' => $content,
                'is_secret' => false,
                'font_color' => '#9333ea',
                'action' => 'system_welcome',
                'welcome_user' => $user->username,
                'sent_at' => now()->toDateTimeString(),
            ];

            $this->chatState->pushMessage($roomId, $botMsg);
            broadcast(new \App\Events\MessageSent($roomId, $botMsg));
            \App\Jobs\SaveMessageJob::dispatch($botMsg);
        }

        return response()->json([
            'status' => 'success',
            'message' => "聊天机器人已{$status}",
            'enabled' => $isEnabled,
        ]);
    }

    /**
     * 测试指定 AI 厂商的接口连通性
     *
     * 通过 GET /v1/models 检查端点可达性与 API Key 有效性，毫秒级响应，
     * 不触发模型推理，避免经 Cloudflare 代理时因推理耗时导致 524 超时。
     *
     * @param  int  $id  厂商配置 ID
     * @return JsonResponse 测试结果（含可用模型列表）
     */
    public function testConnection(int $id): JsonResponse
    {
        $provider = AiProviderConfig::findOrFail($id);

        $apiKey = $provider->getDecryptedApiKey();
        $base = rtrim($provider->api_endpoint, '/');

        // 拼接 /v1/models 端点（检查连通性，不触发推理）
        $modelsUrl = str_ends_with($base, '/v1')
            ? $base.'/models'
            : $base.'/v1/models';

        $startTime = microtime(true);

        try {
            $response = \Illuminate\Support\Facades\Http::withToken($apiKey)
                ->timeout(10)
                ->get($modelsUrl);

            $ms = (int) ((microtime(true) - $startTime) * 1000);

            if (! $response->successful()) {
                return response()->json([
                    'ok' => false,
                    'message' => "HTTP {$response->status()}：{$response->body()}",
                    'ms' => $ms,
                ]);
            }

            $data = $response->json();

            // 提取可用模型列表（兼容 Ollama 和 OpenAI 格式）
            $models = collect($data['models'] ?? $data['data'] ?? [])
                ->pluck('id')
                ->filter()
                ->values()
                ->toArray();

            $modelList = count($models) > 0
                ? implode('、', array_slice($models, 0, 5)).(count($models) > 5 ? ' 等' : '')
                : $provider->model;

            return response()->json([
                'ok' => true,
                'message' => "接口连通正常，可用模型：{$modelList}",
                'ms' => $ms,
                'models' => $models,
            ]);
        } catch (\Illuminate\Http\Client\ConnectionException $e) {
            $ms = (int) ((microtime(true) - $startTime) * 1000);

            return response()->json([
                'ok' => false,
                'message' => '连接失败：'.$e->getMessage(),
                'ms' => $ms,
            ]);
        }
    }

    /**
     * 删除 AI 厂商配置
     *
     * @param  int  $id  厂商配置 ID
     * @return RedirectResponse 重定向到列表页
     */
    public function destroy(int $id): RedirectResponse
    {
        $provider = AiProviderConfig::findOrFail($id);
        $name = $provider->name;
        $provider->delete();

        return redirect()->route('admin.ai-providers.index')
            ->with('success', "已删除 {$name}！");
    }
}
