<?php

namespace App\Filament\Pages;

use App\Services\QuestionServiceApi;
use App\Services\MistakeBookService;
use App\Services\KnowledgeGraphService;
use App\Services\QuestionPromptService;
use App\Services\AiClientService;
use App\Models\Question;
use App\Models\Student;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Log;

class QuestionDetail extends Page
{
    protected static ?string $title = '题目详情';
    protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-document-text';
    protected static ?string $navigationLabel = '题目详情';
    protected static string|\UnitEnum|null $navigationGroup = '题库管理';
    protected static ?int $navigationSort = 4;
    protected static ?string $slug = 'question-detail/{questionId?}';
    protected string $view = 'filament.pages.question-detail';

    public ?string $questionId = null;
    public ?string $sourceType = 'question';
    public ?string $mistakeId = null;
    public ?string $studentId = null;

    public array $questionData = [];
    public array $mistakeData = [];
    public array $relatedQuestions = [];
    public ?string $studentName = null;
    public array $historySummary = [];
    public string $answerOverride = '';

    public function mount(?string $questionId = null): void
    {
        // 检查是否是错题本来源（同时有mistake_id和student_id）
        $this->mistakeId = Request::get('mistake_id');
        $this->studentId = Request::get('student_id');
        $this->questionId = $questionId ?: Request::get('question_id');

        if ($this->mistakeId && $this->studentId) {
            $this->sourceType = 'mistake';
            $this->loadFromMistake();
        } else {
            $this->sourceType = 'question';
            $this->loadFromQuestionBank();
        }

        if (empty($this->questionData)) {
            $this->notifyAndRedirect(
                '未能加载到题目数据，请稍后重试',
                $this->sourceType === 'mistake'
                    ? route('filament.admin.pages.mistake-book')
                    : route('filament.admin.pages.question-management')
            );
        }
    }

    protected function loadFromQuestionBank(): void
    {
        if (!$this->questionId) {
            $this->notifyAndRedirect('缺少题目ID参数', route('filament.admin.pages.question-management'));
            return;
        }

        $question = $this->fetchQuestion($this->questionId);
        if ($question) {
            $this->questionData = $this->prepareQuestionDisplay($question);
            $this->answerOverride = (string) ($this->questionData['answer'] ?? '');
            $this->attachGlobalAccuracy();
        }
    }

    protected function loadFromMistake(): void
    {
        $mistakeService = app(MistakeBookService::class);
        $detail = $mistakeService->getMistakeDetail($this->mistakeId, $this->studentId);

        if (empty($detail)) {
            $this->notifyAndRedirect('未能获取错题详情', route('filament.admin.pages.mistake-book'));
            return;
        }

        $this->mistakeData = $detail;
        $this->questionId = $detail['question_id'] ?? $this->questionId;
        $this->studentName = $detail['student_name'] ?? null;

        $bankQuestion = $this->fetchQuestion($this->questionId);
        $fallbackQuestion = $detail['question'] ?? [];

        if (!$bankQuestion && empty($fallbackQuestion)) {
            $this->notifyAndRedirect('题目不存在或已被删除', route('filament.admin.pages.mistake-book'));
            return;
        }

        $question = array_merge($fallbackQuestion, $bankQuestion ?? []);
        $question = $this->prepareQuestionDisplay($question);

        $this->questionData = array_merge($question, [
            'mistake_info' => [
                'student_answer' => $detail['student_answer'] ?? '',
                'correct' => (bool) ($detail['correct'] ?? false),
                'score' => $detail['score'] ?? null,
                'full_score' => $detail['full_score'] ?? null,
                'partial_score_ratio' => $detail['partial_score_ratio'] ?? null,
                'error_type' => $detail['error_type'] ?? '',
                'mistake_category' => $detail['mistake_category'] ?? '',
                'ai_analysis' => $detail['ai_analysis'] ?? [],
                'created_at' => $detail['created_at'] ?? '',
            ],
        ]);
        $this->answerOverride = (string) ($this->questionData['answer'] ?? '');

        // 尝试从本地学生表补充姓名，避免仅展示ID
        if (!$this->studentName && $this->studentId) {
            try {
                $student = Student::find($this->studentId);
                if ($student && $student->name) {
                    $this->studentName = $student->name;
                }
            } catch (\Throwable $e) {
                Log::warning('Load student name failed', [
                    'student_id' => $this->studentId,
                    'error' => $e->getMessage(),
                ]);
            }
        }

        $this->loadHistorySummary();
        $this->attachGlobalAccuracy();
    }

    protected function fetchQuestion(?string $questionId): ?array
    {
        if (!$questionId) {
            return null;
        }

        try {
            $service = app(QuestionServiceApi::class);
            $response = $service->getQuestionDetail($questionId);
            return $response['data'] ?? null;
        } catch (\Throwable $e) {
            Log::error('Failed to load question detail', [
                'question_id' => $questionId,
                'error' => $e->getMessage(),
            ]);
            return null;
        }
    }

    protected function notifyAndRedirect(string $message, string $route): void
    {
        Notification::make()
            ->title('提示')
            ->body($message)
            ->danger()
            ->send();

        $this->redirect($route);
    }

    public function getTitle(): string
    {
        if ($this->sourceType === 'mistake') {
            $label = $this->questionData['question_number'] ?? ('#' . ($this->mistakeId ?? ''));
            return '错题详情 - ' . $label;
        }

        if (!empty($this->questionData)) {
            return '题目详情 - ' . ($this->questionData['question_code'] ?? $this->questionId);
        }

        return '题目详情';
    }

    public function getBreadcrumbs(): array
    {
        $breadcrumbs = [
            [
                'name' => '题库管理',
                'url' => route('filament.admin.pages.question-management'),
            ],
        ];

        if ($this->sourceType === 'mistake') {
            $breadcrumbs[] = [
                'name' => '错题本',
                'url' => route('filament.admin.pages.mistake-book'),
            ];
        }

        $breadcrumbs[] = [
            'name' => '题目详情',
            'url' => '',
        ];

        return $breadcrumbs;
    }

    public function getDifficultyColor(): string
    {
        if (!isset($this->questionData['difficulty'])) {
            return 'bg-gray-100 text-gray-700';
        }

        $difficulty = (float) $this->questionData['difficulty'];

        if ($difficulty < 0.4) {
            return 'bg-green-100 text-green-700';
        } elseif ($difficulty < 0.7) {
            return 'bg-yellow-100 text-yellow-700';
        }

        return 'bg-red-100 text-red-700';
    }

    public function getDifficultyLabel(): string
    {
        if (!isset($this->questionData['difficulty'])) {
            return '未知';
        }

        $difficulty = (float) $this->questionData['difficulty'];

        if ($difficulty < 0.4) {
            return '简单';
        } elseif ($difficulty < 0.7) {
            return '中等';
        }

        return '困难';
    }

    public function saveAnswerOverride(): void
    {
        if (!$this->questionId) {
            return;
        }

        $question = Question::query()->find($this->questionId);
        if (!$question) {
            Notification::make()
                ->title('题目不存在')
                ->danger()
                ->send();
            return;
        }

        $question->update(['answer' => $this->answerOverride]);
        $this->questionData['answer'] = $this->answerOverride;

        Notification::make()
            ->title('答案已更新')
            ->success()
            ->send();
    }

    public function regenerateSolution(): void
    {
        if (!$this->questionId) {
            return;
        }

        $question = Question::query()->find($this->questionId);
        if (!$question) {
            Notification::make()
                ->title('题目不存在')
                ->danger()
                ->send();
            return;
        }

        $stem = (string) ($this->questionData['stem'] ?? '');
        $answer = (string) ($this->answerOverride ?: ($this->questionData['answer'] ?? ''));
        $images = $this->questionData['images']
            ?? ($this->questionData['meta']['images'] ?? []);

        if (is_string($images)) {
            $decoded = json_decode($images, true);
            $images = is_array($decoded) ? $decoded : [];
        }

        if ($stem === '' || $answer === '') {
            Notification::make()
                ->title('题干或答案为空，无法生成')
                ->warning()
                ->send();
            return;
        }

        try {
            $prompt = app(QuestionPromptService::class)->buildSolutionRegenPrompt($stem, $answer, $images);
            $result = app(AiClientService::class)->callJson($prompt);

            $solution = $result['solution'] ?? '';
            $steps = $result['steps'] ?? [];

            $meta = $question->meta ?? [];
            $meta['solution_steps'] = $steps;

            $question->update([
                'solution' => $solution,
                'answer' => $answer,
                'meta' => $meta,
            ]);

            $this->questionData['solution'] = $solution;
            $this->questionData['answer'] = $answer;
            $this->questionData['meta']['solution_steps'] = $steps;

            Notification::make()
                ->title('解题思路已更新')
                ->success()
                ->send();
        } catch (\Throwable $e) {
            Notification::make()
                ->title('AI 生成失败')
                ->body($e->getMessage())
                ->danger()
                ->send();
        }
    }

    public function getKnowledgePointName(): string
    {
        if (!isset($this->questionData['kp_code'])) {
            return '';
        }

        $kpCode = $this->questionData['kp_code'];

        static $kpMap = null;
        if ($kpMap === null) {
            $kpMap = [];
            try {
                $service = app(KnowledgeGraphService::class);
                $resp = $service->listKnowledgePoints(1, 1000);
                foreach ($resp['data'] ?? [] as $kp) {
                    $code = $kp['kp_code'] ?? $kp['id'] ?? null;
                    if (!$code) {
                        continue;
                    }
                    $kpMap[$code] = $kp['cn_name'] ?? $kp['name'] ?? $code;
                }
            } catch (\Throwable $e) {
                Log::warning('Load knowledge point names failed', [
                    'error' => $e->getMessage(),
                ]);
            }
        }

        return $kpMap[$kpCode] ?? $kpCode;
    }

    public function getSkillNames(): array
    {
        $skillCodes = $this->questionData['skills'] ?? [];
        if (empty($skillCodes) || !is_array($skillCodes)) {
            return [];
        }

        static $skillMap = null;
        if ($skillMap === null) {
            $skillMap = [];
            try {
                $service = app(KnowledgeGraphService::class);
                // 优先拉全量技能映射
                $resp = $service->listSkills(1, 1000);
                $skills = $resp['data'] ?? $resp ?? [];
                if (is_array($skills)) {
                    foreach ($skills as $skill) {
                        $code = $skill['code'] ?? null;
                        if (!$code) {
                            continue;
                        }
                        $skillMap[$code] = $skill['name'] ?? $code;
                    }
                }
                // 如果仍为空，尝试按知识点单独获取
                if (empty($skillMap) && !empty($this->questionData['kp_code'])) {
                    $kpSkills = $service->getSkillsByKnowledgePoint($this->questionData['kp_code']);
                    foreach ($kpSkills as $skill) {
                        $code = $skill['code'] ?? null;
                        if (!$code) {
                            continue;
                        }
                        $skillMap[$code] = $skill['name'] ?? $code;
                    }
                }
            } catch (\Throwable $e) {
                Log::warning('Load skills failed', [
                    'error' => $e->getMessage(),
                ]);
            }
        }

        return array_map(function ($code) use ($skillMap) {
            return $skillMap[$code] ?? $code;
        }, $skillCodes);
    }

    protected function loadHistorySummary(): void
    {
        if (!$this->studentId || !$this->questionId) {
            return;
        }

        try {
            $service = app(MistakeBookService::class);
            $list = $service->listMistakes([
                'student_id' => $this->studentId,
                'per_page' => 100,
            ]);

            $data = $list['data'] ?? [];
            $filtered = array_values(array_filter($data, function ($item) {
                $qid = $item['question_id'] ?? ($item['question']['id'] ?? null);
                if ($qid === null) {
                    return false;
                }
                return (string) $qid === (string) $this->questionId;
            }));

            if (empty($filtered)) {
                return;
            }

            $total = count($filtered);
            $correct = count(array_filter($filtered, fn ($item) => !empty($item['correct'])));
            $latest = collect($filtered)->sortByDesc('created_at')->first();

            $this->historySummary = [
                'total' => $total,
                'correct' => $correct,
                'last_correct' => (bool) ($latest['correct'] ?? false),
                'last_time' => $latest['created_at'] ?? null,
            ];
        } catch (\Throwable $e) {
            Log::warning('Load history summary failed', [
                'student_id' => $this->studentId,
                'question_id' => $this->questionId,
                'error' => $e->getMessage(),
            ]);
        }
    }

    /**
     * 对题干/选项做展示友好化处理：拆分嵌入式选项，保留 display_stem 与 display_options
     */
    protected function prepareQuestionDisplay(array $question): array
    {
        $question['display_stem'] = $question['stem'] ?? '';

        // 规范化选项
        $options = $question['options'] ?? [];
        if (is_string($options)) {
            $decoded = json_decode($options, true);
            if (is_array($decoded)) {
                $options = $decoded;
            }
        }

        // 如果没有单独选项，但题干里嵌入了 A./B./C./D.，尝试提取
        if (empty($options) && !empty($question['stem']) && is_string($question['stem'])) {
            $stem = $question['stem'];
            $parsedOptions = [];
            $pattern = '/(?<![A-Za-z0-9])([A-D])[\\.．、，,\\s]+\\s*(.+?)(?=(?<![A-Za-z0-9])[A-D][\\.．、，,\\s]+|$)/su';

            if (preg_match_all($pattern, $stem, $matches, PREG_SET_ORDER)) {
                foreach ($matches as $match) {
                    $text = trim($match[2]);
                    if ($text !== '') {
                        $parsedOptions[] = $text;
                    }
                }

                // 只接受 2-4 个选项，避免误切分
                if (count($parsedOptions) >= 2 && count($parsedOptions) <= 4) {
                    $options = $parsedOptions;
                    $firstMatchPos = mb_strpos($stem, $matches[0][0]);
                    if ($firstMatchPos !== false) {
                        $question['display_stem'] = trim(mb_substr($stem, 0, $firstMatchPos));
                    }
                }
            }
        }

        $question['display_options'] = $options;
        return $question;
    }

    protected function attachGlobalAccuracy(): void
    {
        if (!$this->questionId) {
            return;
        }

        try {
            $service = app(MistakeBookService::class);
            $accuracy = $service->getQuestionAccuracy($this->questionId);
            if ($accuracy !== null) {
                $this->questionData['global_accuracy'] = $accuracy;
            }
        } catch (\Throwable $e) {
            Log::warning('Attach global accuracy failed', [
                'question_id' => $this->questionId,
                'error' => $e->getMessage(),
            ]);
        }
    }
}
