<?php

namespace App\Services;

use App\Models\Paper;
use App\Models\PaperQuestion;

class PaperPayloadService
{
    public function buildExamContent(Paper $paper): array
    {
        $paper->loadMissing('questions');
        $questions = $paper->questions ?? collect();

        $codes = $this->generatePaperCodes($paper->paper_id);

        return [
            'paper_info' => [
                'paper_id' => $paper->paper_id,
                'paper_name' => $paper->paper_name ?? '',
                'student_id' => $paper->student_id ?? '',
                'teacher_id' => $paper->teacher_id ?? '',
                'total_questions' => $questions->count(),
                'total_score' => $paper->total_score ?? 0,
                'difficulty_category' => $paper->difficulty_category ?? '基础',
                'created_at' => $paper->created_at?->toISOString(),
                'updated_at' => $paper->updated_at?->toISOString(),
                'exam_code' => $codes['exam_code'],
                'grading_code' => $codes['grading_code'],
                'paper_id_num' => $codes['paper_id_num'],
            ],
            'questions' => $questions->map(function (PaperQuestion $q) {
                $options = [];
                if ($q->question_type === 'choice') {
                    $questionText = $q->question_text ?? '';
                    preg_match_all('/([A-D])\s*[\.\、\:]\s*([^A-D]+?)(?=[A-D]\s*[\.\、\:]|$)/u', $questionText, $matches, PREG_SET_ORDER);
                    foreach ($matches as $match) {
                        $options[] = [
                            'label' => $match[1],
                            'content' => trim($match[2]),
                        ];
                    }
                }

                return [
                    'question_number' => $q->question_number,
                    'question_id' => $q->question_id,
                    'question_bank_id' => $q->question_bank_id,
                    'question_type' => $q->question_type,
                    'knowledge_point' => $q->knowledge_point,
                    'difficulty' => $q->difficulty,
                    'score' => $q->score,
                    'estimated_time' => $q->estimated_time,
                    'stem' => $q->question_text ?? '',
                    'options' => $options,
                    'correct_answer' => $q->correct_answer ?? '',
                    'solution' => $q->solution ?? '',
                    'student_answer' => $q->student_answer,
                    'is_correct' => $q->is_correct,
                    'score_obtained' => $q->score_obtained,
                    'score_ratio' => $q->score_ratio,
                    'teacher_comment' => $q->teacher_comment,
                    'graded_at' => $q->graded_at?->toISOString(),
                    'graded_by' => $q->graded_by,
                    'metadata' => [
                        'has_solution' => !empty($q->solution),
                        'is_choice' => $q->question_type === 'choice',
                        'is_fill' => $q->question_type === 'fill',
                        'is_answer' => $q->question_type === 'answer',
                        'difficulty_label' => $this->getDifficultyLabel($q->difficulty),
                        'question_type_label' => $this->getQuestionTypeLabel($q->question_type),
                    ],
                ];
            })->toArray(),
            'statistics' => [
                'type_distribution' => $this->getTypeDistribution($questions),
                'difficulty_distribution' => $this->getDifficultyDistribution($questions),
                'knowledge_point_distribution' => $this->getKnowledgePointDistribution($questions),
                'average_difficulty' => $questions->avg('difficulty'),
                'total_estimated_time' => $questions->sum('estimated_time'),
            ],
            'knowledge_points' => $questions->pluck('knowledge_point')->unique()->filter()->values()->toArray(),
            'skills' => $this->extractSkillsFromQuestions($questions),
        ];
    }

    public function buildPaperApiPayload(Paper $paper): array
    {
        $examContent = $this->buildExamContent($paper);
        $codes = $this->generatePaperCodes($paper->paper_id);

        return [
            'success' => true,
            'paper_id' => $paper->paper_id,
            'status' => 'ready',
            'exam_code' => $codes['exam_code'],
            'grading_code' => $codes['grading_code'],
            'paper_id_num' => $codes['paper_id_num'],
            'exam_content' => $examContent,
            'urls' => [
                'grading_url' => route('filament.admin.auth.intelligent-exam.grading', ['paper_id' => $paper->paper_id]),
                'student_exam_url' => route('filament.admin.auth.intelligent-exam.pdf', ['paper_id' => $paper->paper_id, 'answer' => 'false']),
            ],
            'pdfs' => [
                'exam_paper_pdf' => $paper->exam_pdf_url,
                'grading_pdf' => $paper->grading_pdf_url,
            ],
            'stats' => $examContent['statistics'] ?? null,
            'created_at' => $paper->created_at?->toISOString(),
            'updated_at' => $paper->updated_at?->toISOString(),
        ];
    }

    public function generatePaperCodes(string $paperId): array
    {
        if (preg_match('/paper_(\d{12})/', $paperId, $matches)) {
            $paperIdNum = $matches[1];
        } else {
            $paperIdNum = preg_replace('/[^0-9]/', '', $paperId);
            $paperIdNum = str_pad(substr($paperIdNum, 0, 12), 12, '0', STR_PAD_LEFT);
        }

        return [
            'paper_id_num' => $paperIdNum,
            'exam_code' => '1' . $paperIdNum,
            'grading_code' => '2' . $paperIdNum,
        ];
    }

    private function getQuestionTypeLabel(?string $type): string
    {
        return match ($type) {
            'choice' => '选择题',
            'fill' => '填空题',
            'answer' => '解答题',
            default => '未知题型',
        };
    }

    private function getDifficultyLabel(?float $difficulty): string
    {
        if ($difficulty === null) {
            return '未知';
        }
        if ($difficulty <= 0.4) {
            return '基础';
        }
        if ($difficulty <= 0.7) {
            return '中等';
        }
        return '拔高';
    }

    private function getTypeDistribution($questions): array
    {
        $distribution = [];
        foreach ($questions as $question) {
            $type = $question->question_type;
            $distribution[$type] = ($distribution[$type] ?? 0) + 1;
        }
        return $distribution;
    }

    private function getDifficultyDistribution($questions): array
    {
        $distribution = [];
        foreach ($questions as $question) {
            $label = $this->getDifficultyLabel($question->difficulty);
            $distribution[$label] = ($distribution[$label] ?? 0) + 1;
        }
        return $distribution;
    }

    private function getKnowledgePointDistribution($questions): array
    {
        $distribution = [];
        foreach ($questions as $question) {
            $kp = $question->knowledge_point;
            if ($kp) {
                $distribution[$kp] = ($distribution[$kp] ?? 0) + 1;
            }
        }
        return $distribution;
    }

    private function extractSkillsFromQuestions($questions): array
    {
        $skills = [];
        foreach ($questions as $question) {
            $solution = $question->solution ?? '';
            if ($solution) {
                $skillKeywords = ['代入法', '配方法', '因式分解', '换元法', '判别式', '求根公式', '韦达定理'];
                foreach ($skillKeywords as $keyword) {
                    if (strpos($solution, $keyword) !== false) {
                        $skills[] = $keyword;
                    }
                }
            }

            $stem = $question->question_text ?? '';
            if ($stem) {
                preg_match_all('/\{([^}]+)\}/', $stem, $matches);
                foreach ($matches[1] as $match) {
                    $skillList = array_map('trim', explode(',', $match));
                    $skills = array_merge($skills, $skillList);
                }
            }
        }
        return array_unique(array_filter($skills));
    }
}
