<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;
use App\Models\StudentKnowledgeMastery;
use App\Models\MistakeRecord;
use App\Models\Question;
use App\Models\KnowledgePoint;

class QuestionExpansionService
{
    /**
     * 按优先级扩展题目数量
     * 优先级策略：
     * 1. 优先使用错题记录的题目
     * 2. 错题相同的知识点的其他题目
     * 3. 相同知识点的子知识点的题目
     * 4. 学生薄弱知识点相关题目
     * 5. 薄弱知识点的子知识点的题目
     */
    public function expandQuestions(array $baseParams, ?string $studentId, array $weaknessFilter, int $totalQuestions): array
    {
        Log::info('QuestionExpansionService: 开始题目扩展', [
            'student_id' => $studentId,
            'total_needed' => $totalQuestions,
            'weakness_count' => count($weaknessFilter)
        ]);

        $strategy = [
            'mistake_ids' => $baseParams['mistake_ids'] ?? [],
            'mistake_question_ids' => $baseParams['mistake_question_ids'] ?? [],
            'step2_count' => 0,
            'step3_count' => 0,
            'step4_count' => 0,
            'step5_count' => 0,
            'expansion_details' => []
        ];

        $includeMistakes = ($baseParams['mistake_options']['review_mistakes'] ?? true) && $studentId;

        if (!$includeMistakes) {
            Log::info('QuestionExpansionService: 未开启错题回顾，跳过扩展');
            return $strategy;
        }

        // Step 1: 获取学生历史错题（优先级：最高）
        // 直接使用学生历史错题，学习价值最高
        if (empty($strategy['mistake_question_ids'])) {
            $studentMistakes = $this->getStudentMistakes($studentId);
            $strategy['mistake_question_ids'] = array_values(array_unique(array_column($studentMistakes, 'question_id')));
            $strategy['expansion_details']['step1_mistakes'] = count($strategy['mistake_question_ids']);
            Log::info('QuestionExpansionService: Step1 - 获取历史错题', [
                'count' => count($strategy['mistake_question_ids']),
                'mistake_ids' => $strategy['mistake_question_ids']
            ]);
        }

        // 如果错题数量已满足需求，直接返回
        if (count($strategy['mistake_question_ids']) >= $totalQuestions) {
            Log::info('QuestionExpansionService: Step1 - 错题数量已满足需求', [
                'total_needed' => $totalQuestions,
                'mistake_count' => count($strategy['mistake_question_ids'])
            ]);
            return $strategy;
        }

        // Step 2: 错题相同的知识点的其他题目（优先级：高）
        // 强化特定知识点的掌握，题目类型多样化
        $remaining = $totalQuestions - count($strategy['mistake_question_ids']);
        $mistakeKps = $this->getMistakeKnowledgePoints($studentId, $strategy['mistake_question_ids']);
        if (!empty($mistakeKps) && $remaining > 0) {
            $step2Questions = $this->getQuestionsByKnowledgePoints($mistakeKps, $strategy['mistake_question_ids'], $remaining);
            $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step2Questions);
            $strategy['step2_count'] = count($step2Questions);
            $strategy['expansion_details']['step2_same_kp'] = [
                'knowledge_points' => $mistakeKps,
                'added_count' => count($step2Questions)
            ];
            Log::info('QuestionExpansionService: Step2 - 获取同知识点其他题目', [
                'knowledge_points' => $mistakeKps,
                'added_count' => count($step2Questions),
                'total_count' => count($strategy['mistake_question_ids'])
            ]);
        }

        // 如果数量仍不足，继续扩展
        $remaining = $totalQuestions - count($strategy['mistake_question_ids']);
        if ($remaining <= 0) {
            return $strategy;
        }

        // Step 3: 相同知识点的子知识点的题目（优先级：中高）
        // 深入知识点的细分类别，实现精准练习
        if (!empty($mistakeKps) && $remaining > 0) {
            $childKps = $this->getChildKnowledgePoints($mistakeKps);
            if (!empty($childKps)) {
                $step3Questions = $this->getQuestionsByKnowledgePoints($childKps, $strategy['mistake_question_ids'], $remaining);
                $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step3Questions);
                $strategy['step3_count'] = count($step3Questions);
                $strategy['expansion_details']['step3_child_kp'] = [
                    'child_knowledge_points' => $childKps,
                    'added_count' => count($step3Questions)
                ];
                Log::info('QuestionExpansionService: Step3 - 获取子知识点题目', [
                    'child_knowledge_points' => $childKps,
                    'added_count' => count($step3Questions),
                    'total_count' => count($strategy['mistake_question_ids'])
                ]);
            }
        }

        // 如果数量仍不足，继续扩展
        $remaining = $totalQuestions - count($strategy['mistake_question_ids']);
        if ($remaining <= 0) {
            return $strategy;
        }

        // Step 4: 学生薄弱知识点相关题目（优先级：中）
        // 针对性强化薄弱环节，提升整体掌握度
        if (!empty($weaknessFilter) && $remaining > 0) {
            $weaknessKps = array_column($weaknessFilter, 'kp_code');
            $step4Questions = $this->getQuestionsByKnowledgePoints($weaknessKps, $strategy['mistake_question_ids'], $remaining);
            $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step4Questions);
            $strategy['step4_count'] = count($step4Questions);
            $strategy['expansion_details']['step4_weakness'] = [
                'weakness_knowledge_points' => $weaknessKps,
                'added_count' => count($step4Questions)
            ];
            Log::info('QuestionExpansionService: Step4 - 获取薄弱知识点题目', [
                'weakness_knowledge_points' => $weaknessKps,
                'added_count' => count($step4Questions),
                'total_count' => count($strategy['mistake_question_ids'])
            ]);
        }

        // 如果数量仍不足，继续扩展
        $remaining = $totalQuestions - count($strategy['mistake_question_ids']);
        if ($remaining <= 0) {
            return $strategy;
        }

        // Step 5: 薄弱知识点的子知识点的题目（优先级：低）
        // 全面覆盖薄弱环节的各个细分领域
        if (!empty($weaknessFilter) && $remaining > 0) {
            $weaknessKps = array_column($weaknessFilter, 'kp_code');
            $childWeaknessKps = $this->getChildKnowledgePoints($weaknessKps);
            if (!empty($childWeaknessKps)) {
                $step5Questions = $this->getQuestionsByKnowledgePoints($childWeaknessKps, $strategy['mistake_question_ids'], $remaining);
                $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step5Questions);
                $strategy['step5_count'] = count($step5Questions);
                $strategy['expansion_details']['step5_child_weakness'] = [
                    'child_weakness_knowledge_points' => $childWeaknessKps,
                    'added_count' => count($step5Questions)
                ];
                Log::info('QuestionExpansionService: Step5 - 获取薄弱点子知识点题目', [
                    'child_weakness_knowledge_points' => $childWeaknessKps,
                    'added_count' => count($step5Questions),
                    'total_count' => count($strategy['mistake_question_ids'])
                ]);
            }
        }

        Log::info('QuestionExpansionService: 题目扩展完成', [
            'total_final_count' => count($strategy['mistake_question_ids']),
            'expansion_details' => $strategy['expansion_details']
        ]);

        return $strategy;
    }

    /**
     * 获取学生错题（去重，按question_id分组）
     */
    private function getStudentMistakes(string $studentId): array
    {
        try {
            // 使用 MistakeRecord 模型获取学生的错题（不限制数量，获取全部）
            // 按 question_id 分组去重，保留第一条记录
            $mistakeRecords = MistakeRecord::forStudent($studentId)
                ->where('review_status', '!=', MistakeRecord::REVIEW_STATUS_MASTERED) // 排除已掌握的错题
                ->select(['question_id', 'knowledge_point', 'error_type', 'difficulty'])
                ->get()
                ->unique('question_id') // 按 question_id 去重
                ->values(); // 重新索引

            Log::info('QuestionExpansionService: 获取学生错题（去重后）', [
                'student_id' => $studentId,
                'total_records' => MistakeRecord::forStudent($studentId)
                    ->where('review_status', '!=', MistakeRecord::REVIEW_STATUS_MASTERED)->count(),
                'unique_count' => $mistakeRecords->count()
            ]);

            return $mistakeRecords->map(function ($record) {
                return [
                    'question_id' => $record->question_id,
                    'kp_code' => $record->knowledge_point,
                    'error_type' => $record->error_type,
                    'difficulty' => $record->difficulty,
                ];
            })->toArray();

        } catch (\Exception $e) {
            Log::error('QuestionExpansionService: 获取学生错题失败', [
                'student_id' => $studentId,
                'error' => $e->getMessage()
            ]);

            return [];
        }
    }

    /**
     * 获取错题对应的知识点
     */
    private function getMistakeKnowledgePoints(string $studentId, array $questionIds): array
    {
        $mistakeRecords = MistakeRecord::forStudent($studentId)
            ->whereIn('question_id', $questionIds)
            ->whereNotNull('knowledge_point')
            ->select(['knowledge_point'])
            ->get();

        return array_values(array_unique(array_filter($mistakeRecords->pluck('knowledge_point')->toArray())));
    }

    /**
     * 根据知识点获取题目
     */
    private function getQuestionsByKnowledgePoints(array $kpCodes, array $excludeQuestionIds, int $limit): array
    {
        if (empty($kpCodes)) {
            return [];
        }

        try {
            $questions = Question::whereIn('kp_code', $kpCodes)
                ->whereNotIn('id', $excludeQuestionIds)
                ->select(['id'])
                ->limit($limit)
                ->get();

            return $questions->pluck('id')->toArray();

        } catch (\Exception $e) {
            Log::warning('QuestionExpansionService: 获取题目失败', [
                'kp_codes' => $kpCodes,
                'limit' => $limit,
                'error' => $e->getMessage()
            ]);
            return [];
        }
    }

    /**
     * 获取子知识点
     */
    private function getChildKnowledgePoints(array $parentKpCodes): array
    {
        try {
            $childKps = KnowledgePoint::whereIn('parent_kp_code', $parentKpCodes)
                ->select(['kp_code'])
                ->get();

            return $childKps->pluck('kp_code')->toArray();

        } catch (\Exception $e) {
            Log::warning('QuestionExpansionService: 获取子知识点失败', [
                'parent_kp_codes' => $parentKpCodes,
                'error' => $e->getMessage()
            ]);
            return [];
        }
    }

    /**
     * 获取扩展统计信息
     */
    public function getExpansionStats(array $strategy): array
    {
        return [
            'total_questions' => count($strategy['mistake_question_ids'] ?? []),
            'step1_mistakes' => count($strategy['mistake_question_ids'] ?? []),
            'step2_same_kp' => $strategy['step2_count'] ?? 0,
            'step3_child_kp' => $strategy['step3_count'] ?? 0,
            'step4_weakness' => $strategy['step4_count'] ?? 0,
            'step5_child_weakness' => $strategy['step5_count'] ?? 0,
            'expansion_rate' => $this->calculateExpansionRate($strategy),
            'details' => $strategy['expansion_details'] ?? []
        ];
    }

    /**
     * 计算扩展率
     */
    private function calculateExpansionRate(array $strategy): float
    {
        $totalExpanded = ($strategy['step2_count'] ?? 0) +
                        ($strategy['step3_count'] ?? 0) +
                        ($strategy['step4_count'] ?? 0) +
                        ($strategy['step5_count'] ?? 0);

        $totalQuestions = count($strategy['mistake_question_ids'] ?? []);

        if ($totalQuestions === 0) {
            return 0.0;
        }

        return round(($totalExpanded / $totalQuestions) * 100, 2);
    }

    /**
     * 按知识点优先级扩展题目数量（按知识点组卷专用）
     * 优先级策略：
     * 1. 直接关联知识点题目（来自输入数组）
     * 2. 相同知识点其他题目
     * 3. 子知识点题目（下探1层）
     * 4. 薄弱知识点题目
     * 5. 子知识点题目（下探2层）
     */
    public function expandQuestionsByKnowledgePoints(array $baseParams, ?string $studentId, array $targetKnowledgePoints, array $weaknessFilter, int $totalQuestions): array
    {
        Log::info('QuestionExpansionService: 开始按知识点扩展题目', [
            'student_id' => $studentId,
            'target_knowledge_points' => $targetKnowledgePoints,
            'total_needed' => $totalQuestions,
            'weakness_count' => count($weaknessFilter)
        ]);

        $strategy = [
            'mistake_ids' => [],
            'mistake_question_ids' => [],
            'step2_count' => 0,
            'step3_count' => 0,
            'step4_count' => 0,
            'step5_count' => 0,
            'expansion_details' => []
        ];

        // Step 1: 获取直接关联知识点题目（优先级：最高）
        // 直接使用用户指定的知识点数组中的题目
        if (!empty($targetKnowledgePoints)) {
            $step1Questions = $this->getQuestionsByKnowledgePoints($targetKnowledgePoints, $strategy['mistake_question_ids'], $totalQuestions);
            $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step1Questions);
            $strategy['expansion_details']['step1_direct_kp'] = [
                'target_knowledge_points' => $targetKnowledgePoints,
                'added_count' => count($step1Questions)
            ];
            Log::info('QuestionExpansionService: Step1 - 获取直接关联知识点题目', [
                'target_knowledge_points' => $targetKnowledgePoints,
                'added_count' => count($step1Questions),
                'total_count' => count($strategy['mistake_question_ids'])
            ]);
        }

        // 如果直接关联题目数量已满足需求，直接返回
        if (count($strategy['mistake_question_ids']) >= $totalQuestions) {
            Log::info('QuestionExpansionService: Step1 - 直接关联知识点题目数量已满足需求', [
                'total_needed' => $totalQuestions,
                'direct_kp_count' => count($strategy['mistake_question_ids'])
            ]);
            return $strategy;
        }

        // Step 2: 相同知识点其他题目（优先级：高）
        // 强化特定知识点的掌握，题目类型多样化
        $remaining = $totalQuestions - count($strategy['mistake_question_ids']);
        if (!empty($targetKnowledgePoints) && $remaining > 0) {
            $step2Questions = $this->getQuestionsByKnowledgePoints($targetKnowledgePoints, $strategy['mistake_question_ids'], $remaining);
            $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step2Questions);
            $strategy['step2_count'] = count($step2Questions);
            $strategy['expansion_details']['step2_same_kp'] = [
                'knowledge_points' => $targetKnowledgePoints,
                'added_count' => count($step2Questions)
            ];
            Log::info('QuestionExpansionService: Step2 - 获取相同知识点其他题目', [
                'knowledge_points' => $targetKnowledgePoints,
                'added_count' => count($step2Questions),
                'total_count' => count($strategy['mistake_question_ids'])
            ]);
        }

        // 如果数量仍不足，继续扩展
        $remaining = $totalQuestions - count($strategy['mistake_question_ids']);
        if ($remaining <= 0) {
            return $strategy;
        }

        // Step 3: 子知识点题目（下探1层）（优先级：中高）
        // 深入知识点的细分类别，实现精准练习
        if (!empty($targetKnowledgePoints) && $remaining > 0) {
            $childKps = $this->getChildKnowledgePoints($targetKnowledgePoints);
            if (!empty($childKps)) {
                $step3Questions = $this->getQuestionsByKnowledgePoints($childKps, $strategy['mistake_question_ids'], $remaining);
                $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step3Questions);
                $strategy['step3_count'] = count($step3Questions);
                $strategy['expansion_details']['step3_child_kp_level1'] = [
                    'child_knowledge_points' => $childKps,
                    'added_count' => count($step3Questions)
                ];
                Log::info('QuestionExpansionService: Step3 - 获取子知识点题目（下探1层）', [
                    'child_knowledge_points' => $childKps,
                    'added_count' => count($step3Questions),
                    'total_count' => count($strategy['mistake_question_ids'])
                ]);
            }
        }

        // 如果数量仍不足，继续扩展
        $remaining = $totalQuestions - count($strategy['mistake_question_ids']);
        if ($remaining <= 0) {
            return $strategy;
        }

        // Step 4: 薄弱知识点题目（优先级：中）
        // 针对性强化薄弱环节，提升整体掌握度
        if (!empty($weaknessFilter) && $remaining > 0) {
            $weaknessKps = array_column($weaknessFilter, 'kp_code');
            // 排除已使用的目标知识点
            $weaknessKps = array_diff($weaknessKps, $targetKnowledgePoints);
            if (!empty($weaknessKps)) {
                $step4Questions = $this->getQuestionsByKnowledgePoints($weaknessKps, $strategy['mistake_question_ids'], $remaining);
                $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step4Questions);
                $strategy['step4_count'] = count($step4Questions);
                $strategy['expansion_details']['step4_weakness'] = [
                    'weakness_knowledge_points' => $weaknessKps,
                    'added_count' => count($step4Questions)
                ];
                Log::info('QuestionExpansionService: Step4 - 获取薄弱知识点题目', [
                    'weakness_knowledge_points' => $weaknessKps,
                    'added_count' => count($step4Questions),
                    'total_count' => count($strategy['mistake_question_ids'])
                ]);
            }
        }

        // 如果数量仍不足，继续扩展
        $remaining = $totalQuestions - count($strategy['mistake_question_ids']);
        if ($remaining <= 0) {
            return $strategy;
        }

        // Step 5: 子知识点题目（下探2层）（优先级：低）
        // 全面覆盖薄弱环节的各个细分领域
        if (!empty($weaknessFilter) && $remaining > 0) {
            $weaknessKps = array_column($weaknessFilter, 'kp_code');
            // 排除已使用的目标知识点
            $weaknessKps = array_diff($weaknessKps, $targetKnowledgePoints);
            if (!empty($weaknessKps)) {
                $childWeaknessKps = $this->getChildKnowledgePoints($weaknessKps);
                if (!empty($childWeaknessKps)) {
                    $step5Questions = $this->getQuestionsByKnowledgePoints($childWeaknessKps, $strategy['mistake_question_ids'], $remaining);
                    $strategy['mistake_question_ids'] = array_merge($strategy['mistake_question_ids'], $step5Questions);
                    $strategy['step5_count'] = count($step5Questions);
                    $strategy['expansion_details']['step5_child_weakness_level2'] = [
                        'child_weakness_knowledge_points' => $childWeaknessKps,
                        'added_count' => count($step5Questions)
                    ];
                    Log::info('QuestionExpansionService: Step5 - 获取薄弱点子知识点题目（下探2层）', [
                        'child_weakness_knowledge_points' => $childWeaknessKps,
                        'added_count' => count($step5Questions),
                        'total_count' => count($strategy['mistake_question_ids'])
                    ]);
                }
            }
        }

        Log::info('QuestionExpansionService: 按知识点题目扩展完成', [
            'total_final_count' => count($strategy['mistake_question_ids']),
            'target_knowledge_points' => $targetKnowledgePoints,
            'expansion_details' => $strategy['expansion_details']
        ]);

        return $strategy;
    }

    /**
     * 获取子知识点（下探多层）
     * 支持追溯下探两层
     */
    private function getChildKnowledgePointsMultiLevel(array $parentKpCodes, int $maxDepth = 2): array
    {
        $allChildKps = [];
        $currentLevelKps = $parentKpCodes;
        $depth = 0;

        while ($depth < $maxDepth && !empty($currentLevelKps)) {
            Log::info('QuestionExpansionService: 获取子知识点', [
                'depth' => $depth + 1,
                'parent_kp_codes' => $currentLevelKps
            ]);

            $childKps = $this->getChildKnowledgePoints($currentLevelKps);
            if (!empty($childKps)) {
                $allChildKps = array_merge($allChildKps, $childKps);
                $currentLevelKps = $childKps; // 下一层的父级是这一层的子级
            } else {
                break; // 没有更多子知识点时停止
            }
            $depth++;
        }

        // 去重
        return array_values(array_unique($allChildKps));
    }
}
