<?php

namespace App\Services;

use App\DTO\ExamAnalysisDataDto;
use App\DTO\ReportPayloadDto;
use App\Models\Paper;
use App\Models\PaperQuestion;
use App\Models\Student;
use Illuminate\Support\Facades\Log;

/**
 * 学情报告核心服务
 * 负责协调学情报告生成的完整流程
 */
class ExamAnalysisService
{
    public function __construct(
        private readonly TaskManager $taskManager,
        private readonly LearningAnalyticsService $learningAnalyticsService,
        private readonly QuestionBankService $questionBankService,
        private readonly ExamPdfExportService $pdfExportService,
        private readonly QuestionServiceApi $questionServiceApi,
        private readonly ExamAnswerAnalysisService $examAnswerAnalysisService
    ) {}

    /**
     * 生成学情报告
     * 异步模式，立即返回任务ID
     */
    public function generateReport(string $paperId, string $studentId, ?string $recordId = null): string
    {
        // 创建异步任务
        $taskId = $this->taskManager->createTask(
            TaskManager::TASK_TYPE_ANALYSIS,
            compact('paperId', 'studentId', 'recordId')
        );

        Log::info('ExamAnalysisService: 开始生成学情报告', [
            'task_id' => $taskId,
            'paper_id' => $paperId,
            'student_id' => $studentId,
            'record_id' => $recordId,
        ]);

        // 触发后台处理（实际项目中应使用队列）
        // dispatch(new AnalysisReportJob($taskId));
        // 目前使用同步调用模拟异步
        $this->processReportGeneration($taskId, $paperId, $studentId, $recordId);

        return $taskId;
    }

    /**
     * 获取分析数据（同步模式）
     * 用于页面直接展示，不生成PDF
     */
    public function getAnalysisData(string $paperId, string $studentId, ?string $recordId = null): ExamAnalysisDataDto
    {
        try {
            Log::info('ExamAnalysisService: 获取分析数据', compact('paperId', 'studentId'));

            // 获取试卷数据
            $paperData = $this->getPaperData($paperId);
            if (!$paperData) {
                throw new \Exception('未找到试卷数据');
            }

            // 获取学生数据
            $studentData = $this->getStudentData($studentId);

            // 获取题目数据
            $questionsData = $this->getQuestionsData($paperId, $paperData);

            // 获取分析数据
            $analysisData = $this->getLearningAnalysisData($paperId, $studentId, $paperData);

            // 获取掌握度数据
            $masteryData = $this->getMasteryData($studentId);

            // 获取学习建议
            $recommendations = $this->getLearningRecommendations($studentId);

            $dto = new ExamAnalysisDataDto(
                paper: $paperData,
                student: $studentData,
                questions: $questionsData,
                mastery: $masteryData,
                insights: $analysisData,
                recommendations: $recommendations,
                analysisId: $paperData['analysis_id'] ?? null
            );

            Log::info('ExamAnalysisService: 分析数据获取完成', [
                'paper_id' => $paperId,
                'student_id' => $studentId,
                'question_count' => count($questionsData),
                'has_analysis' => !empty($analysisData),
            ]);

            return $dto;

        } catch (\Exception $e) {
            Log::error('ExamAnalysisService: 获取分析数据失败', [
                'paper_id' => $paperId,
                'student_id' => $studentId,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * 处理报告生成（后台任务）
     */
    private function processReportGeneration(string $taskId, string $paperId, string $studentId, ?string $recordId): void
    {
        try {
            $this->taskManager->updateTaskProgress($taskId, 10, '正在获取分析数据...');

            // 获取分析数据
            $analysisData = $this->getAnalysisData($paperId, $studentId, $recordId);

            $this->taskManager->updateTaskProgress($taskId, 50, '正在生成PDF报告...');

            // 生成PDF
            $pdfUrl = $this->pdfExportService->generateAnalysisReportPdf($paperId, $studentId, $recordId);

            if (!$pdfUrl) {
                throw new \Exception('PDF生成失败');
            }

            $this->taskManager->updateTaskProgress($taskId, 90, '正在保存报告...');

            // 保存PDF URL到数据库
            $this->savePdfUrl($paperId, $studentId, $recordId, $pdfUrl);

            // 标记任务完成
            $this->taskManager->markTaskCompleted($taskId, [
                'pdf_url' => $pdfUrl,
            ]);

            Log::info('ExamAnalysisService: 学情报告生成完成', [
                'task_id' => $taskId,
                'paper_id' => $paperId,
                'student_id' => $studentId,
                'pdf_url' => $pdfUrl,
            ]);

            // 发送回调通知
            $this->taskManager->sendCallback($taskId);

        } catch (\Exception $e) {
            Log::error('ExamAnalysisService: 报告生成失败', [
                'task_id' => $taskId,
                'paper_id' => $paperId,
                'student_id' => $studentId,
                'error' => $e->getMessage(),
            ]);

            $this->taskManager->markTaskFailed($taskId, $e->getMessage());
        }
    }

    /**
     * 获取试卷数据
     */
    private function getPaperData(string $paperId): ?array
    {
        $paper = Paper::with(['questions' => function ($query) {
            $query->orderBy('question_number')->orderBy('id');
        }])->find($paperId);

        if (!$paper) {
            return null;
        }

        return [
            'id' => $paper->paper_id,
            'paper_id' => $paper->paper_id,
            'name' => $paper->paper_name,
            'total_questions' => $paper->question_count,
            'total_score' => $paper->total_score,
            'analysis_id' => $paper->analysis_id,
            'created_at' => $paper->created_at->toISOString(),
        ];
    }

    /**
     * 获取学生数据
     */
    private function getStudentData(string $studentId): array
    {
        $student = Student::find($studentId);

        return [
            'id' => $student?->student_id ?? $studentId,
            'student_id' => $student?->student_id ?? $studentId,
            'name' => $student?->name ?? $studentId,
            'grade' => $student?->grade ?? '未知年级',
            'class' => $student?->class_name ?? '未知班级',
        ];
    }

    /**
     * 获取题目数据
     */
    private function getQuestionsData(string $paperId, array $paperData): array
    {
        $paper = Paper::with('questions')->find($paperId);
        if (!$paper || $paper->questions->isEmpty()) {
            return [];
        }

        $kpNameMap = $this->getKnowledgePointNameMap();
        $questionDetails = $this->getQuestionDetails($paper);

        $questions = [];
        $sortedQuestions = $paper->questions->sortBy(function (PaperQuestion $q, int $idx) {
            $number = $q->question_number ?? $idx + 1;
            return is_numeric($number) ? (float) $number : ($q->id ?? $idx);
        });

        foreach ($sortedQuestions as $idx => $question) {
            $kpCode = $question->knowledge_point ?? '';
            $kpName = $kpNameMap[$kpCode] ?? $kpCode ?: '未标注';
            $detail = $questionDetails[(string) ($question->question_id ?? '')] ?? [];
            $solution = $detail['solution'] ?? $detail['解析'] ?? $detail['analysis'] ?? null;
            $typeRaw = $question->question_type ?? ($detail['question_type'] ?? $detail['type'] ?? '');
            $normalizedType = $this->normalizeQuestionType($typeRaw);
            $number = $question->question_number ?? ($idx + 1);

            $questions[] = [
                'question_number' => $number,
                'question_text' => is_array($question->question_text)
                    ? json_encode($question->question_text, JSON_UNESCAPED_UNICODE)
                    : ($question->question_text ?? ''),
                'question_type' => $normalizedType,
                'knowledge_point' => $kpCode,
                'knowledge_point_name' => $kpName,
                'score' => $question->score,
                'solution' => $solution,
            ];
        }

        return $questions;
    }

    /**
     * 获取学习分析数据（修改为本地数据库查询）
     */
    private function getLearningAnalysisData(string $paperId, string $studentId, array $paperData): array
    {
        $analysisData = [];

        if (!empty($paperData['analysis_id'])) {
            Log::info('ExamAnalysisService: 从本地数据库获取分析数据', [
                'paper_id' => $paperId,
                'student_id' => $studentId,
                'analysis_id' => $paperData['analysis_id']
            ]);

            $analysisRecord = \DB::table('exam_analysis_results')
                ->where('id', $paperData['analysis_id'])
                ->where('student_id', $studentId)
                ->first();

            if ($analysisRecord && !empty($analysisRecord->analysis_data)) {
                $analysisData = json_decode($analysisRecord->analysis_data, true);
                Log::info('ExamAnalysisService: 成功获取本地分析数据', [
                    'data_size' => strlen($analysisRecord->analysis_data)
                ]);
            } else {
                Log::warning('ExamAnalysisService: 未找到本地分析数据', [
                    'paper_id' => $paperId,
                    'student_id' => $studentId,
                    'analysis_id' => $paperData['analysis_id']
                ]);
            }
        }

        return $analysisData;
    }

    /**
     * 获取掌握度数据（修改为使用本地方法）
     */
    private function getMasteryData(string $studentId): array
    {
        try {
            Log::info('ExamAnalysisService: 获取学生掌握度概览', [
                'student_id' => $studentId
            ]);
            $masteryOverview = $this->learningAnalyticsService->getStudentMasteryOverview($studentId);
            $masteryData = $masteryOverview['details'] ?? [];
            Log::info('ExamAnalysisService: 成功获取掌握度数据', [
                'count' => count($masteryData)
            ]);
            return $masteryData;
        } catch (\Exception $e) {
            Log::error('ExamAnalysisService: 获取掌握度数据失败', [
                'student_id' => $studentId,
                'error' => $e->getMessage()
            ]);
            return [];
        }
    }

    /**
     * 获取学习建议（修改为使用本地方法）
     */
    private function getLearningRecommendations(string $studentId): array
    {
        try {
            Log::info('ExamAnalysisService: 获取学习路径推荐', [
                'student_id' => $studentId
            ]);
            $learningPaths = $this->learningAnalyticsService->recommendLearningPaths($studentId, 3);
            $recommendations = $learningPaths['recommendations'] ?? [];
            Log::info('ExamAnalysisService: 成功获取学习路径推荐', [
                'count' => count($recommendations)
            ]);
            return $recommendations;
        } catch (\Exception $e) {
            Log::error('ExamAnalysisService: 获取学习路径推荐失败', [
                'student_id' => $studentId,
                'error' => $e->getMessage()
            ]);
            return [];
        }
    }

    /**
     * 获取知识点名称映射
     */
    private function getKnowledgePointNameMap(): array
    {
        try {
            $options = $this->questionServiceApi->getKnowledgePointOptions();
            return $options ?: [];
        } catch (\Exception $e) {
            Log::warning('ExamAnalysisService: 获取知识点名称失败', [
                'error' => $e->getMessage(),
            ]);
            return [];
        }
    }

    /**
     * 获取题目详情
     */
    private function getQuestionDetails(Paper $paper): array
    {
        $details = [];
        $questionIds = $paper->questions->pluck('question_id')->filter()->unique()->values();

        foreach ($questionIds as $qid) {
            try {
                $detail = $this->questionBankService->getQuestion((string) $qid);
                if (!empty($detail)) {
                    $details[(string) $qid] = $detail;
                }
            } catch (\Throwable $e) {
                Log::warning('ExamAnalysisService: 获取题目详情失败', [
                    'question_id' => $qid,
                    'error' => $e->getMessage(),
                ]);
            }
        }

        return $details;
    }

    /**
     * 构建掌握度摘要
     */
    private function buildMasterySummary(array $masteryData): array
    {
        $items = [];
        $total = 0;
        $count = 0;

        foreach ($masteryData as $row) {
            $code = $row['kp_code'] ?? null;
            $name = $row['kp_name'] ?? ($code ?? '未知知识点');
            $level = (float) ($row['mastery_level'] ?? 0);
            $delta = $row['mastery_change'] ?? null;

            $items[] = [
                'kp_code' => $code,
                'kp_name' => $name,
                'mastery_level' => $level,
                'mastery_change' => $delta,
            ];

            $total += $level;
            $count++;
        }

        $average = $count > 0 ? round($total / $count, 2) : null;

        // 按掌握度从低到高排序
        usort($items, fn($a, $b) => ($a['mastery_level'] <=> $b['mastery_level']));

        return [
            'items' => $items,
            'average' => $average,
            'weak_list' => array_slice($items, 0, 5),
        ];
    }

    /**
     * 标准化题型
     */
    private function normalizeQuestionType(string $type): string
    {
        $t = strtolower(trim($type));
        return match (true) {
            str_contains($t, 'choice') || str_contains($t, '选择') => 'choice',
            str_contains($t, 'fill') || str_contains($t, 'blank') || str_contains($t, '填空') => 'fill',
            default => 'answer',
        };
    }

    /**
     * 保存PDF URL到数据库
     */
    private function savePdfUrl(string $paperId, string $studentId, ?string $recordId, string $pdfUrl): void
    {
        try {
            if ($recordId) {
                // OCR记录
                $ocrRecord = \App\Models\OCRRecord::find($recordId);
                if ($ocrRecord) {
                    $ocrRecord->update(['analysis_pdf_url' => $pdfUrl]);
                }
            } else {
                // 学生记录 - 使用新的 student_reports 表
                \App\Models\StudentReport::updateOrCreate(
                    [
                        'student_id' => $studentId,
                        'report_type' => 'exam_analysis',
                        'paper_id' => $paperId,
                    ],
                    [
                        'pdf_url' => $pdfUrl,
                        'generation_status' => 'completed',
                        'generated_at' => now(),
                        'updated_at' => now(),
                    ]
                );

                Log::info('ExamAnalysisService: PDF URL已保存到student_reports表', [
                    'paper_id' => $paperId,
                    'student_id' => $studentId,
                    'pdf_url' => $pdfUrl,
                ]);
            }
        } catch (\Throwable $e) {
            Log::error('ExamAnalysisService: 保存PDF URL失败', [
                'paper_id' => $paperId,
                'student_id' => $studentId,
                'record_id' => $recordId,
                'error' => $e->getMessage(),
            ]);
        }
    }

    /**
     * 使用步骤级分析算法分析考试答题数据
     *
     * 这是基于《卷子分析思考.md》思路的增强版分析方法
     * 支持步骤级分析、知识点映射和智能出卷推荐
     *
     * @param array $examData 考试数据，包含题目和步骤信息
     * @return array 分析结果
     *
     * 示例输入：
     * [
     *   'paper_id' => 'exam_001',
     *   'student_id' => 'student_001',
     *   'questions' => [
     *     [
     *       'question_id' => 'Q1',
     *       'score' => 5,
     *       'score_obtained' => 3,
     *       'steps' => [
     *         ['step_index' => 1, 'is_correct' => true, 'kp_id' => 'K-SQRT-SIMPLE'],
     *         ['step_index' => 2, 'is_correct' => false, 'kp_id' => 'K-NUM-ADD-SUB']
     *       ]
     *     ]
     *   ]
     * ]
     */
    public function analyzeWithSteps(array $examData): array
    {
        Log::info('ExamAnalysisService: 开始步骤级分析', [
            'paper_id' => $examData['paper_id'] ?? 'unknown',
            'student_id' => $examData['student_id'] ?? 'unknown',
            'question_count' => count($examData['questions'] ?? [])
        ]);

        try {
            // 使用增强的分析算法
            $result = $this->examAnswerAnalysisService->analyzeExamAnswers($examData);

            Log::info('ExamAnalysisService: 步骤级分析完成', [
                'paper_id' => $examData['paper_id'],
                'student_id' => $examData['student_id'],
                'knowledge_points_analyzed' => count($result['knowledge_point_analysis'] ?? [])
            ]);

            return $result;

        } catch (\Exception $e) {
            Log::error('ExamAnalysisService: 步骤级分析失败', [
                'paper_id' => $examData['paper_id'] ?? 'unknown',
                'student_id' => $examData['student_id'] ?? 'unknown',
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            throw new \Exception('步骤级分析失败：' . $e->getMessage());
        }
    }

    /**
     * 获取步骤级分析结果
     *
     * @param string $studentId
     * @param string $paperId
     * @return array|null
     */
    public function getStepAnalysisResult(string $studentId, string $paperId): ?array
    {
        try {
            $result = \DB::connection('pgsql')
                ->table('exam_analysis_results')
                ->where('student_id', $studentId)
                ->where('paper_id', $paperId)
                ->orderBy('created_at', 'desc')
                ->first();

            if (!$result) {
                return null;
            }

            return json_decode($result->analysis_data, true);

        } catch (\Exception $e) {
            Log::error('ExamAnalysisService: 获取步骤级分析结果失败', [
                'student_id' => $studentId,
                'paper_id' => $paperId,
                'error' => $e->getMessage()
            ]);

            return null;
        }
    }
}
