<?php

namespace App\Services;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
use App\Models\Student;

class StudentProgressService
{
    /**
     * 获取单个学生的学习进度
     */
    public function getProgress(string $studentId): array
    {
        Log::info('获取学生学习进度', ['student_id' => $studentId]);

        $studentGrade = Student::query()
            ->where('student_id', $studentId)
            ->value('grade');

        // 获取知识图谱结构
        $graphData = $this->getKnowledgeGraphStructure($studentGrade ? (int) $studentGrade : null);
        $leafKpCodes = $graphData['leafKpCodes'];
        $leafKpCodesSet = $graphData['leafKpCodesSet'];
        $kpCodes = $graphData['kpCodes'];
        $maxChildScore = count($leafKpCodes) * 1.0;

        // 获取学生掌握度数据
        $mergedData = $this->getStudentMasteryData($studentId);
        $mergedCountBefore = count($mergedData);
        // 仅保留叶子节点数据，避免父节点干扰进度
        $mergedData = array_filter($mergedData, function ($item) use ($leafKpCodesSet) {
            return isset($leafKpCodesSet[$item['kp_code']]);
        });
        if ($mergedCountBefore > 0 && count($mergedData) !== $mergedCountBefore) {
            Log::info('学习进度过滤父节点', [
                'student_id' => $studentId,
                'before' => $mergedCountBefore,
                'after' => count($mergedData),
            ]);
        }

        // 如果没有数据，返回空结构（和批量接口行为一致）
        if (empty($mergedData)) {
            return [
                'success' => true,
                'data' => [
                    'student_id' => $studentId,
                    'learning_progress' => 0,
                    'learning_progress_percentage' => 0,
                    'mastered_child_count' => 0,
                    'total_child_count' => count($leafKpCodes),
                    'child_mastery_sum' => 0,
                    'has_data' => false,
                    'calculated_at' => now()->toISOString()
                ],
                'message' => '该学生暂无学习数据'
            ];
        }

        // 筛选叶子节点
        $childMasteryData = collect($mergedData);

        // 如果没有子知识点数据，也返回空结构
        if ($childMasteryData->isEmpty()) {
            return [
                'success' => true,
                'data' => [
                    'student_id' => $studentId,
                    'learning_progress' => 0,
                    'learning_progress_percentage' => 0,
                    'mastered_child_count' => 0,
                    'total_child_count' => count($leafKpCodes),
                    'child_mastery_sum' => 0,
                    'has_data' => false,
                    'calculated_at' => now()->toISOString()
                ],
                'message' => '该学生暂无子知识点学习数据'
            ];
        }

        // 计算学习进度
        $totalChildMasterySum = $childMasteryData->sum('mastery_level');
        $learningProgress = $maxChildScore > 0 ? ($totalChildMasterySum / $maxChildScore) : 0.0;

        // 统计信息
        $statistics = [
            'total_knowledge_points' => count($kpCodes),
            'child_knowledge_points' => count($leafKpCodes),
            'student_mastered_child_count' => $childMasteryData->count(),
            'student_mastered_child_percentage' => round(($childMasteryData->count() / count($leafKpCodes)) * 100, 2),
            'child_mastery_sum' => round($totalChildMasterySum, 4),
            'max_child_score' => round($maxChildScore, 4),
            'learning_progress_percentage' => round($learningProgress * 100, 2),
            'data_source' => 'student_knowledge_mastery',
            'child_mastery_max' => round($childMasteryData->max('mastery_level'), 4),
            'child_mastery_min' => round($childMasteryData->min('mastery_level'), 4),
            'child_mastery_avg' => round($childMasteryData->avg('mastery_level'), 4),
        ];

        Log::info('学生学习进度计算成功', [
            'student_id' => $studentId,
            'learning_progress' => $learningProgress,
        ]);

        return [
            'success' => true,
            'data' => [
                'student_id' => $studentId,
                'learning_progress' => round($learningProgress, 6),
                'learning_progress_percentage' => round($learningProgress * 100, 2),
                'mastered_child_count' => $childMasteryData->count(),
                'total_child_count' => count($leafKpCodes),
                'child_mastery_sum' => round($totalChildMasterySum, 4),
                'has_data' => true,
                'child_knowledge_points' => $childMasteryData->values()->toArray(),
                'statistics' => $statistics,
                'calculated_at' => now()->toISOString()
            ],
            'message' => '学习进度计算成功'
        ];
    }

    /**
     * 批量获取学生学习进度
     */
    public function getBatchProgress(array $studentIds): array
    {
        if (empty($studentIds)) {
            return [
                'success' => false,
                'error' => 'student_ids 不能为空'
            ];
        }

        if (count($studentIds) > 100) {
            return [
                'success' => false,
                'error' => '单次最多查询 100 个学生'
            ];
        }

        Log::info('批量获取学生学习进度', ['count' => count($studentIds)]);

        $gradeMap = Student::query()
            ->whereIn('student_id', $studentIds)
            ->pluck('grade', 'student_id')
            ->toArray();

        $stageGraph = [];
        $stageStats = [];

        // 批量获取掌握度数据
        $batchData = $this->getBatchStudentMasteryData($studentIds);
        $detailedData = $batchData['detailed'];
        $simpleData = $batchData['simple'];

        // 为每个学生计算学习进度
        $results = [];

        foreach ($studentIds as $studentId) {
            $studentId = (string) $studentId;
            $grade = $gradeMap[$studentId] ?? null;
            $stageKey = $this->getStageKey($grade ? (int) $grade : null);

            if (!isset($stageGraph[$stageKey])) {
                $stageGraph[$stageKey] = $this->getKnowledgeGraphStructure($grade ? (int) $grade : null);
                $stageStats[$stageKey] = [
                    'total_child_knowledge_points' => count($stageGraph[$stageKey]['leafKpCodes']),
                    'student_count' => 0,
                ];
            }
            $stageStats[$stageKey]['student_count']++;
            $leafKpCodesSet = $stageGraph[$stageKey]['leafKpCodesSet'];
            $maxChildScore = count($stageGraph[$stageKey]['leafKpCodes']) * 1.0;
            $mergedData = [];

            // 从 student_knowledge_mastery 获取
            if (isset($detailedData[$studentId])) {
                foreach ($detailedData[$studentId] as $item) {
                    $mergedData[$item->kp_code] = [
                        'kp_code' => $item->kp_code,
                        'mastery_level' => (float) $item->mastery_level,
                    ];
                }
            }

            // 从 student_mastery 补充或更新
            if (isset($simpleData[$studentId])) {
                foreach ($simpleData[$studentId] as $item) {
                    $kpCode = $item->kp_code;
                    $masteryLevel = (float) $item->mastery;

                    if (isset($mergedData[$kpCode])) {
                        if ($masteryLevel > $mergedData[$kpCode]['mastery_level']) {
                            $mergedData[$kpCode]['mastery_level'] = $masteryLevel;
                        }
                    } else {
                        $mergedData[$kpCode] = [
                            'kp_code' => $kpCode,
                            'mastery_level' => $masteryLevel,
                        ];
                    }
                }
            }

            // 计算学习进度
            if (empty($mergedData)) {
                $results[$studentId] = [
                    'student_id' => $studentId,
                    'learning_progress' => 0,
                    'learning_progress_percentage' => 0,
                    'mastered_child_count' => 0,
                    'total_child_count' => count($stageGraph[$stageKey]['leafKpCodes']),
                    'has_data' => false,
                ];
                continue;
            }

            $mergedCountBefore = count($mergedData);
            // 仅保留叶子节点数据，避免父节点干扰进度
            $mergedData = array_filter($mergedData, function ($item) use ($leafKpCodesSet) {
                return isset($leafKpCodesSet[$item['kp_code']]);
            });
            if ($mergedCountBefore > 0 && count($mergedData) !== $mergedCountBefore) {
                Log::info('批量学习进度过滤父节点', [
                    'student_id' => $studentId,
                    'before' => $mergedCountBefore,
                    'after' => count($mergedData),
                ]);
            }

            // 筛选叶子节点并计算
            $childMasterySum = 0;
            $masteredChildCount = 0;

            foreach ($mergedData as $item) {
                if (isset($leafKpCodesSet[$item['kp_code']])) {
                    $childMasterySum += $item['mastery_level'];
                    $masteredChildCount++;
                }
            }

            $learningProgress = $maxChildScore > 0 ? ($childMasterySum / $maxChildScore) : 0.0;

            $results[$studentId] = [
                'student_id' => $studentId,
                'learning_progress' => round($learningProgress, 6),
                'learning_progress_percentage' => round($learningProgress * 100, 2),
                'mastered_child_count' => $masteredChildCount,
                'total_child_count' => count($stageGraph[$stageKey]['leafKpCodes']),
                'child_mastery_sum' => round($childMasterySum, 4),
                'has_data' => true,
            ];
        }

        Log::info('批量学习进度计算完成', ['count' => count($results)]);

        return [
            'success' => true,
            'data' => $results,
            'meta' => [
                'total_students' => count($studentIds),
                'stage_summary' => $stageStats,
                'calculated_at' => now()->toISOString(),
            ]
        ];
    }

    /**
     * 获取知识图谱结构（缓存 5 分钟）
     */
    private function getKnowledgeGraphStructure(?int $grade = null): array
    {
        $stageKey = $this->getStageKey($grade);
        $cacheKey = 'knowledge_graph_structure_' . $stageKey;

        return Cache::remember($cacheKey, 300, function () use ($grade) {
            $query = DB::connection('remote_mysql')
                ->table('knowledge_points')
                ->select(['kp_code', 'parent_kp_code', 'grade']);

            $stageLabel = $this->getStageLabel($grade);
            if ($stageLabel) {
                $query->where('grade', $stageLabel);
            }

            $allKps = $query->get();

            $kpCodes = $allKps->pluck('kp_code')->toArray();
            $parentCodes = $allKps->whereNotNull('parent_kp_code')->pluck('parent_kp_code')->unique()->toArray();
            $leafKpCodes = array_values(array_diff($kpCodes, $parentCodes));
            $maxDepth = $this->calculateMaxDepth($allKps);

            return [
                'kpCodes' => $kpCodes,
                'leafKpCodes' => $leafKpCodes,
                'leafKpCodesSet' => array_flip($leafKpCodes),
                'maxDepth' => $maxDepth,
            ];
        });
    }

    private function getStageLabel(?int $grade): ?string
    {
        if ($grade === null || $grade <= 0) {
            return null;
        }

        if ($grade <= 6) {
            return '小学';
        }

        if ($grade <= 9) {
            return '初中';
        }

        return '高中';
    }

    private function getStageKey(?int $grade): string
    {
        $label = $this->getStageLabel($grade);
        return $label ?: 'all';
    }

    private function calculateMaxDepth($knowledgePoints): int
    {
        $children = [];
        foreach ($knowledgePoints as $kp) {
            if (!empty($kp->parent_kp_code)) {
                $children[$kp->parent_kp_code][] = $kp->kp_code;
            }
        }

        $depthCache = [];
        $maxDepth = 1;
        $visit = function ($kpCode) use (&$visit, &$children, &$depthCache, &$maxDepth): int {
            if (isset($depthCache[$kpCode])) {
                return $depthCache[$kpCode];
            }
            if (empty($children[$kpCode])) {
                $depthCache[$kpCode] = 1;
                return 1;
            }
            $childDepths = array_map(fn ($child) => $visit($child), $children[$kpCode]);
            $depthCache[$kpCode] = 1 + max($childDepths);
            $maxDepth = max($maxDepth, $depthCache[$kpCode]);
            return $depthCache[$kpCode];
        };

        foreach ($knowledgePoints as $kp) {
            $visit($kp->kp_code);
        }

        return $maxDepth;
    }

    /**
     * 获取单个学生的掌握度数据
     */
    private function getStudentMasteryData(string $studentId): array
    {
        $mergedData = [];

        try {
            $detailedData = DB::connection('remote_mysql')
                ->table('student_knowledge_mastery')
                ->where('student_id', $studentId)
                ->select(['kp_code', 'mastery_level', 'total_attempts', 'correct_attempts', 'updated_at'])
                ->get();

            foreach ($detailedData as $item) {
                $mergedData[$item->kp_code] = [
                    'kp_code' => $item->kp_code,
                    'mastery_level' => (float) $item->mastery_level,
                    'total_attempts' => $item->total_attempts,
                    'correct_attempts' => $item->correct_attempts,
                    'source_table' => 'student_knowledge_mastery',
                    'updated_at' => $item->updated_at
                ];
            }
        } catch (\Exception $e) {
            Log::warning('从 student_knowledge_mastery 获取数据失败', ['error' => $e->getMessage()]);
        }

        return $mergedData;
    }

    /**
     * 批量获取学生掌握度数据
     */
    private function getBatchStudentMasteryData(array $studentIds): array
    {
        $detailedData = DB::connection('remote_mysql')
            ->table('student_knowledge_mastery')
            ->whereIn('student_id', $studentIds)
            ->select(['student_id', 'kp_code', 'mastery_level'])
            ->get()
            ->groupBy('student_id');

        return [
            'detailed' => $detailedData->toArray(),
            'simple' => [],
        ];
    }
}
