<?php

declare(strict_types=1);

namespace Kylin\Prompt\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

/**
 * 防沉迷提示文案服务
 *
 * 按年龄段差异化提示：
 * - 未满8周岁：禁止游戏，提示"根据国家规定，未满8周岁的用户不可使用网络游戏服务"
 * - 8-16周岁：仅周五/六/日及法定节假日20:00-21:00，单次充值≤50元，月累计≤200元
 * - 16-18周岁：仅周五/六/日及法定节假日20:00-21:00，单次充值≤100元，月累计≤400元
 * - 已满18周岁：健康游戏忠告提示
 *
 * 提示场景：
 * - login: 登录提示
 * - time_limit: 时段限制提示
 * - duration_warning: 时长预警提示
 * - payment_limit: 消费限额提示
 * - kick: 强制下线提示
 * - health_advice: 健康游戏忠告
 * - guardian_bind: 监护人绑定提示
 * - face_verify: 人脸识别提示
 * - report_channel: 举报渠道提示
 */
class PromptService
{
    /**
     * 获取提示文案
     *
     * @param int $ageGroup 年龄段 0=未满8 1=8-16 2=16-18 3=已满18
     * @param string $scene 提示场景
     * @param array $context 上下文变量
     */
    public function getPrompt(int $ageGroup, string $scene, array $context = []): array
    {
        $cacheKey = "kylin:prompt:{$ageGroup}:{$scene}";

        return Cache::remember($cacheKey, config('kylin-prompt.cache_ttl', 3600), function () use ($ageGroup, $scene) {
            $record = \DB::table('kp_prompts')
                ->where('age_group', $ageGroup)
                ->where('scene', $scene)
                ->where('status', 1)
                ->first();

            if ($record) {
                return [
                    'title' => $record->title,
                    'content' => $record->content,
                    'type' => $record->popup_type ?? 'modal',
                ];
            }

            // 降级到默认文案
            return $this->getDefaultPrompt($ageGroup, $scene);
        });
    }

    /**
     * 获取某年龄段所有提示
     */
    public function getPromptsByAgeGroup(int $ageGroup): array
    {
        return Cache::remember("kylin:prompt:all:{$ageGroup}", config('kylin-prompt.cache_ttl', 3600), function () use ($ageGroup) {
            return \DB::table('kp_prompts')
                ->where('age_group', $ageGroup)
                ->where('status', 1)
                ->get()
                ->keyBy('scene')
                ->map(fn ($r) => [
                    'title' => $r->title,
                    'content' => $r->content,
                    'type' => $r->popup_type ?? 'modal',
                ])
                ->toArray();
        });
    }

    /**
     * 默认提示文案（硬编码兜底，确保版号审核必过）
     */
    private function getDefaultPrompt(int $ageGroup, string $scene): array
    {
        $defaults = $this->getDefaultPrompts();
        $key = "{$ageGroup}.{$scene}";

        return $defaults[$key] ?? [
            'title' => '提示',
            'content' => '请遵守健康游戏规则',
            'type' => 'modal',
        ];
    }

    /**
     * 版号审核标准提示文案
     * 严格按照《关于防止未成年人沉迷网络游戏的通知》及2026年补充规定
     */
    private function getDefaultPrompts(): array
    {
        return [
            // === 未满8周岁 ===
            '0.login' => [
                'title' => '温馨提示',
                'content' => '根据国家规定，未满8周岁的用户不可使用网络游戏服务。感谢您的理解与配合。',
                'type' => 'modal',
            ],
            '0.time_limit' => [
                'title' => '游戏时间限制',
                'content' => '根据国家规定，未满8周岁的用户不可使用网络游戏服务。',
                'type' => 'modal',
            ],
            '0.payment_limit' => [
                'title' => '消费限制',
                'content' => '根据国家规定，未满8周岁的用户不可使用网络游戏服务，不可进行游戏消费。',
                'type' => 'modal',
            ],
            '0.kick' => [
                'title' => '强制下线',
                'content' => '根据国家规定，未满8周岁的用户不可使用网络游戏服务，您已被强制下线。如有疑问，请联系监护人或拨打未成年人服务专线。',
                'type' => 'modal',
            ],

            // === 8-16周岁 ===
            '1.login' => [
                'title' => '健康游戏忠告',
                'content' => '抵制不良游戏 拒绝盗版游戏 注意自我保护 谨防受骗上当 适度游戏益脑 沉迷游戏伤身 合理安排时间 享受健康生活',
                'type' => 'modal',
            ],
            '1.time_limit' => [
                'title' => '游戏时间限制',
                'content' => '根据国家规定，8周岁以上未满16周岁的未成年人用户，仅可在周五、周六、周日及法定节假日每日20:00至21:00使用网络游戏服务。',
                'type' => 'modal',
            ],
            '1.duration_warning' => [
                'title' => '游戏时长提醒',
                'content' => '您今日的游戏时间即将结束，请注意休息。根据国家规定，8周岁以上未满16周岁的未成年人用户每日游戏时间不得超过1小时。',
                'type' => 'toast',
            ],
            '1.payment_limit' => [
                'title' => '消费限额提醒',
                'content' => '根据国家规定，8周岁以上未满16周岁的未成年人用户，单次充值金额不得超过50元人民币，每月充值金额累计不得超过200元人民币。',
                'type' => 'modal',
            ],
            '1.kick' => [
                'title' => '强制下线',
                'content' => '根据国家规定，您今日的游戏时间已结束，系统将强制您下线。请在允许的时段内合理安排游戏时间。如有疑问，请联系监护人或拨打未成年人服务专线。',
                'type' => 'modal',
            ],
            '1.guardian_bind' => [
                'title' => '监护人绑定',
                'content' => '为保障未成年人权益，建议您的监护人绑定监护关系，以便更好地管理您的游戏行为。',
                'type' => 'modal',
            ],
            '1.face_verify' => [
                'title' => '人脸识别验证',
                'content' => '根据防沉迷系统要求，需要对您进行人脸识别验证，以确认您的身份信息。如拒绝验证，将按照未成年人标准进行游戏限制。',
                'type' => 'modal',
            ],
            '1.report_channel' => [
                'title' => '举报渠道',
                'content' => '如发现游戏存在违规内容或未成年人保护措施不到位的情况，请通过以下渠道举报：游戏内举报功能、未成年人服务专线、12315消费者投诉热线。',
                'type' => 'modal',
            ],

            // === 16-18周岁 ===
            '2.login' => [
                'title' => '健康游戏忠告',
                'content' => '抵制不良游戏 拒绝盗版游戏 注意自我保护 谨防受骗上当 适度游戏益脑 沉迷游戏伤身 合理安排时间 享受健康生活',
                'type' => 'modal',
            ],
            '2.time_limit' => [
                'title' => '游戏时间限制',
                'content' => '根据国家规定，16周岁以上未满18周岁的未成年人用户，仅可在周五、周六、周日及法定节假日每日20:00至21:00使用网络游戏服务。',
                'type' => 'modal',
            ],
            '2.duration_warning' => [
                'title' => '游戏时长提醒',
                'content' => '您今日的游戏时间即将结束，请注意休息。根据国家规定，16周岁以上未满18周岁的未成年人用户每日游戏时间不得超过1小时。',
                'type' => 'toast',
            ],
            '2.payment_limit' => [
                'title' => '消费限额提醒',
                'content' => '根据国家规定，16周岁以上未满18周岁的未成年人用户，单次充值金额不得超过100元人民币，每月充值金额累计不得超过400元人民币。',
                'type' => 'modal',
            ],
            '2.kick' => [
                'title' => '强制下线',
                'content' => '根据国家规定，您今日的游戏时间已结束，系统将强制您下线。请在允许的时段内合理安排游戏时间。如有疑问，请联系监护人或拨打未成年人服务专线。',
                'type' => 'modal',
            ],
            '2.guardian_bind' => [
                'title' => '监护人绑定',
                'content' => '为保障未成年人权益，建议您的监护人绑定监护关系，以便更好地管理您的游戏行为。',
                'type' => 'modal',
            ],
            '2.face_verify' => [
                'title' => '人脸识别验证',
                'content' => '根据防沉迷系统要求，需要对您进行人脸识别验证，以确认您的身份信息。如拒绝验证，将按照未成年人标准进行游戏限制。',
                'type' => 'modal',
            ],
            '2.report_channel' => [
                'title' => '举报渠道',
                'content' => '如发现游戏存在违规内容或未成年人保护措施不到位的情况，请通过以下渠道举报：游戏内举报功能、未成年人服务专线、12315消费者投诉热线。',
                'type' => 'modal',
            ],

            // === 已满18周岁 ===
            '3.login' => [
                'title' => '健康游戏忠告',
                'content' => '抵制不良游戏 拒绝盗版游戏 注意自我保护 谨防受骗上当 适度游戏益脑 沉迷游戏伤身 合理安排时间 享受健康生活',
                'type' => 'modal',
            ],
            '3.health_advice' => [
                'title' => '健康游戏提示',
                'content' => '您已连续游戏较长时间，请注意适当休息，合理安排游戏时间，享受健康生活。',
                'type' => 'toast',
            ],
            '3.report_channel' => [
                'title' => '举报渠道',
                'content' => '如发现游戏存在违规内容或未成年人保护措施不到位的情况，请通过以下渠道举报：游戏内举报功能、未成年人服务专线、12315消费者投诉热线。',
                'type' => 'modal',
            ],
        ];
    }

    /**
     * 清除提示缓存
     */
    public function clearCache(): void
    {
        for ($i = 0; $i <= 3; $i++) {
            Cache::forget("kylin:prompt:all:{$i}");
        }
        // 清除所有场景缓存
        $scenes = ['login', 'time_limit', 'duration_warning', 'payment_limit', 'kick', 'health_advice', 'guardian_bind', 'face_verify', 'report_channel'];
        for ($i = 0; $i <= 3; $i++) {
            foreach ($scenes as $scene) {
                Cache::forget("kylin:prompt:{$i}:{$scene}");
            }
        }

        $this->audit('prompt_cache_cleared', []);
    }

    /**
     * 根据实际年龄获取年龄组
     *
     * 依据《未成年人保护法》及 T/CADPA 14-2021：
     *  - 0: 未满 8 周岁
     *  - 1: 8-16 周岁
     *  - 2: 16-18 周岁
     *  - 3: 已满 18 周岁
     */
    public function getAgeGroup(int $age): int
    {
        return match (true) {
            $age < 8 => 0,
            $age < 16 => 1,
            $age < 18 => 2,
            default => 3,
        };
    }

    /**
     * 根据实际年龄获取登录提示语（便捷方法）
     *
     * 依据《未成年人保护法》第七十五条：网络游戏服务提供者应当要求未成年人以真实身份信息注册并登录。
     */
    public function getAgePrompt(int $age): array
    {
        $ageGroup = $this->getAgeGroup($age);
        return $this->getPrompt($ageGroup, 'login');
    }

    /**
     * 获取所有年龄分组的登录提示语
     *
     * @return array<int, array>
     */
    public function getAllPrompts(): array
    {
        $result = [];
        for ($i = 0; $i <= 3; $i++) {
            $result[$i] = $this->getPrompt($i, 'login');
        }
        return $result;
    }

    /**
     * 获取健康游戏忠告（全年龄通用）
     *
     * 依据《关于防止未成年人沉迷网络游戏的通知》：
     * 健康游戏忠告应包含"适度游戏、拒绝沉迷"等内容。
     */
    public function getHealthAdvice(int $ageGroup): array
    {
        return $this->getPrompt($ageGroup, 'health_advice');
    }

    /**
     * 记录提示文案审计日志
     *
     * 依据《未成年人保护法》和防沉迷相关规定，
     * 提示文案变更、缓存刷新等操作需记录审计日志。
     */
    private function audit(string $event, array $extra = []): void
    {
        if (! class_exists(\Kylin\AuditLog\Models\AuditLog::class)) {
            return;
        }

        try {
            \Kylin\AuditLog\Models\AuditLog::create([
                'event' => $event,
                'model_type' => 'prompt',
                'model_id' => 0,
                'new_values' => $extra,
                'old_values' => null,
                'user_id' => auth()->id(),
                'ip' => request()?->ip(),
                'url' => request()?->fullUrl(),
                'tag' => 'prompt',
            ]);
        } catch (\Throwable $e) {
            Log::warning('提示文案审计日志写入失败', [
                'error' => $e->getMessage(),
                'event' => $event,
            ]);
        }
    }
}
