<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;

/**
 * 知识点掌握情况服务
 *
 * 提供：
 * 1. 获取学生知识点掌握情况统计
 * 2. 获取知识点图谱数据（考试快照）
 * 3. 获取知识点图谱快照列表
 */
class KnowledgeMasteryService
{
    protected string $learningAnalyticsBase;
    protected string $knowledgeServiceBase;
    protected int $timeout;

    public function __construct(?string $learningAnalyticsBase = null, ?string $knowledgeServiceBase = null, ?int $timeout = null)
    {
        // 已迁移到本地，使用MasteryCalculator
        $this->learningAnalyticsBase = '';
        $this->knowledgeServiceBase = rtrim(
            $knowledgeServiceBase
                ?: config('services.knowledge_service.url', env('KNOWLEDGE_SERVICE_API_BASE', 'http://localhost:5011')),
            '/'
        );

        $this->timeout = 20;
    }

    /**
     * 获取学生知识点掌握情况统计
     *
     * @param string $studentId 学生ID
     * @return array
     */
    public function getStats(string $studentId): array
    {
        try {
            // 使用本地的MasteryCalculator
            $masteryCalculator = app(MasteryCalculator::class);
            $overview = $masteryCalculator->getStudentMasteryOverview($studentId);

            // 转换为兼容格式
            $body = [
                'student_id' => $studentId,
                'total_knowledge_points' => $overview['total_knowledge_points'],
                'average_mastery' => $overview['average_mastery_level'],
                'mastered_count' => $overview['mastered_knowledge_points'],
                'good_count' => $overview['good_knowledge_points'],
                'weak_count' => $overview['weak_knowledge_points'],
                'details' => $overview['details'],
            ];

            // 丰富知识点名称（如果有knowledge_points表）
            $body = $this->enrichWithKnowledgePointNames($body);

            // 添加知识图谱总数统计
            $graphStats = $this->getKnowledgeGraphStats();
            $body['graph_total_knowledge_points'] = $graphStats['total'] ?? 0;

            Log::info('KnowledgeMasteryService::getStats (Local)', ['student_id' => $studentId]);
            return [
                'success' => true,
                'data' => $body,
            ];
        } catch (\Throwable $e) {
            Log::error('Knowledge mastery stats exception', [
                'student_id' => $studentId,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'error' => '获取知识点掌握情况异常: ' . $e->getMessage(),
            ];
        }
    }

    /**
     * 丰富知识点名称
     */
    private function enrichWithKnowledgePointNames(array $data): array
    {
        if (empty($data['details'])) {
            return $data;
        }

        // 确保 details 是数组格式（处理 stdClass 对象）
        $details = $data['details'];
        if (!is_array($details)) {
            $details = [];
        } elseif (isset($details[0]) && is_object($details[0])) {
            // 将 stdClass 对象转换为关联数组
            $details = array_map(function ($item) {
                return (array) $item;
            }, $details);
        }

        // 收集所有kp_code
        $kpCodes = array_column($details, 'kp_code');
        if (empty($kpCodes)) {
            return $data;
        }

        // 批量获取知识点名称
        $kpNames = $this->getKnowledgePointNames($kpCodes);

        // 丰富details数据
        foreach ($details as &$detail) {
            $kpCode = $detail['kp_code'] ?? null;
            if ($kpCode && isset($kpNames[$kpCode])) {
                $detail['kp_name'] = $kpNames[$kpCode];
            } else {
                $detail['kp_name'] = $kpCode; // fallback to code
            }
        }

        // 更新原始数据
        $data['details'] = $details;

        return $data;
    }

    /**
     * 批量获取知识点名称
     */
    private function getKnowledgePointNames(array $kpCodes): array
    {
        $result = [];

        foreach ($kpCodes as $kpCode) {
            $name = $this->getKnowledgePointName($kpCode);
            if ($name) {
                $result[$kpCode] = $name;
            }
        }

        return $result;
    }

    /**
     * 批量获取知识点名称映射（返回关联数组）
     */
    private function getKnowledgePointNamesMap(array $kpCodes): array
    {
        $result = [];

        foreach ($kpCodes as $kpCode) {
            $name = $this->getKnowledgePointName($kpCode);
            // 如果获取不到名称，使用kpCode作为默认值
            $result[$kpCode] = $name ?: $kpCode;
        }

        return $result;
    }

    /**
     * 获取单个知识点名称（带缓存）
     * 【优化】直接从MySQL数据库查询，不再调用知识图谱API
     */
    private function getKnowledgePointName(string $kpCode): ?string
    {
        $cacheKey = "kp_name_{$kpCode}";

        return Cache::remember($cacheKey, 3600, function () use ($kpCode) {
            // 【优化】直接从MySQL数据库查询知识点名称
            try {
                $kpName = \DB::table('knowledge_points')
                    ->where('kp_code', $kpCode)
                    ->value('name');

                if ($kpName) {
                    Log::debug('从数据库获取知识点名称', ['kp_code' => $kpCode, 'kp_name' => $kpName]);
                    return $kpName;
                }
            } catch (\Throwable $e) {
                Log::debug('从数据库查询知识点名称失败，将使用本地映射', [
                    'kp_code' => $kpCode,
                    'error' => $e->getMessage(),
                ]);
            }

            // 如果数据库中没有，使用本地映射
            return $this->getLocalKnowledgePointName($kpCode);
        });
    }

    /**
     * 本地知识点名称映射（作为备选方案）
     */
    private function getLocalKnowledgePointName(string $kpCode): ?string
    {
        // 常见的数学知识点中文名称映射
        $nameMap = [
            'A09' => '因式分解',
            'E01' => '一元二次方程',
            'E03' => '一元二次方程的解法',
            'E04' => '一元二次方程的应用',
            'E06' => '判别式',
            'F03' => '函数的概念',
            'F05' => '函数的图像',
            'F06' => '函数的性质',
            'G02' => '几何图形',
            'G03' => '三角形',
            'R06' => '实数',
            'S01' => '三角函数',
            'S02' => '正弦函数',
            'S03' => '余弦函数',
            'S05' => '正切函数',
            'E01B' => '因式分解法',
            'E03B' => '公式法',
            'E04B' => '配方法',
            'G02B' => '平行四边形',
            'G03E' => '等腰三角形',
            'G03G' => '等边三角形',
            'M01C' => '有理数',
            'M04E' => '不等式',
            'PY02' => '概率初步',
            'ST04' => '统计与概率',
            'M04E1' => '一元一次不等式',
            'PY02D' => '随机事件',
            'SIM02' => '相似三角形',
            'ST04D' => '数据的收集',
            'APP_E4' => '应用题',
            'SIM02A' => '相似比',
        ];

        return $nameMap[$kpCode] ?? null;
    }

    /**
     * 判断知识点是否为另一个知识点的子知识点
     */
    private function isChildOf(string $childCode, string $parentCode): bool
    {
        // 常见的父子关系映射
        $parentChildMap = [
            'E01' => ['E01B'], // 一元二次方程 -> 因式分解法
            'E03' => ['E03B'], // 一元二次方程的解法 -> 公式法
            'E04' => ['E04B'], // 一元二次方程的应用 -> 配方法
            'G02' => ['G02B'], // 几何图形 -> 平行四边形
            'G03' => ['G03E', 'G03G'], // 三角形 -> 等腰三角形, 等边三角形
            'M04E' => ['M04E1'], // 不等式 -> 一元一次不等式
            'PY02' => ['PY02D'], // 概率初步 -> 随机事件
            'SIM02' => ['SIM02A'], // 相似三角形 -> 相似比
            'ST04' => ['ST04D'], // 统计与概率 -> 数据的收集
            'G03' => ['G03E', 'G03G'], // 三角形 -> 等腰三角形, 等边三角形
        ];

        // 直接通过代码前缀判断
        if (strpos($childCode, $parentCode) === 0 && $childCode !== $parentCode) {
            return true;
        }

        // 通过映射表判断
        if (isset($parentChildMap[$parentCode]) && in_array($childCode, $parentChildMap[$parentCode])) {
            return true;
        }

        return false;
    }

    /**
     * 获取知识图谱统计信息（带缓存）
     */
    public function getKnowledgeGraphStats(): array
    {
        return Cache::remember('knowledge_graph_stats', 3600, function () {
            try {
                $response = Http::timeout(10)
                    ->get($this->knowledgeServiceBase . '/knowledge-points/');

                if ($response->successful()) {
                    $data = $response->json();
                    $items = $data['data'] ?? $data ?? [];

                    return [
                        'total' => count($items),
                        'updated_at' => now()->toISOString(),
                    ];
                }
            } catch (\Throwable $e) {
                Log::error('Failed to get knowledge graph stats', [
                    'error' => $e->getMessage(),
                ]);
            }

            return ['total' => 0];
        });
    }

    /**
     * 获取学生知识点图谱数据
     *
     * @param string $studentId 学生ID
     * @param string|null $examId 考试ID（可选，不指定则返回最新快照）
     * @return array
     */
    public function getGraph(string $studentId, ?string $examId = null): array
    {
        try {
            // 使用本地的MasteryCalculator
            $masteryCalculator = app(MasteryCalculator::class);
            $overview = $masteryCalculator->getStudentMasteryOverview($studentId);

            // 转换为图谱格式
            $nodes = [];
            $edges = [];

            foreach ($overview['details'] as $detail) {
                $masteryLevel = floatval($detail->mastery_level ?? 0);
                $kpCode = $detail->kp_code;

                // 节点
                $nodes[] = [
                    'id' => $kpCode,
                    'label' => $kpCode,
                    'mastery' => $masteryLevel,
                    'mastery_level' => $this->getMasteryLevelLabel($masteryLevel),
                    'color' => $this->getMasteryColor($masteryLevel),
                    'size' => 20 + ($masteryLevel * 20),
                ];

                // 这里可以添加知识点之间的依赖关系边
                // 暂时为空，后续从knowledge_points表获取
            }

            $graphData = [
                'nodes' => $nodes,
                'edges' => $edges,
                'statistics' => [
                    'total_nodes' => count($nodes),
                    'total_edges' => count($edges),
                    'average_mastery' => $overview['average_mastery_level'],
                ],
            ];

            Log::info('KnowledgeMasteryService::getGraph (Local)', ['student_id' => $studentId, 'exam_id' => $examId]);
            return [
                'success' => true,
                'data' => $graphData,
            ];
        } catch (\Throwable $e) {
            Log::error('Knowledge graph exception', [
                'student_id' => $studentId,
                'exam_id' => $examId,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'error' => '获取知识点图谱异常: ' . $e->getMessage(),
            ];
        }
    }

    /**
     * 获取掌握度等级标签
     */
    private function getMasteryLevelLabel(float $mastery): string
    {
        if ($mastery >= 0.85) return 'mastered';
        if ($mastery >= 0.70) return 'good';
        if ($mastery >= 0.50) return 'fair';
        return 'weak';
    }

    /**
     * 获取掌握度颜色
     */
    private function getMasteryColor(float $mastery): string
    {
        if ($mastery >= 0.85) return '#52c41a'; // 绿色 - 掌握
        if ($mastery >= 0.70) return '#1890ff'; // 蓝色 - 良好
        if ($mastery >= 0.50) return '#faad14'; // 橙色 - 一般
        return '#ff4d4f'; // 红色 - 薄弱
    }

    /**
     * 获取学生知识点图谱快照列表
     *
     * @param string $studentId 学生ID
     * @param int $limit 返回数量限制
     * @return array
     */
    public function getGraphSnapshots(string $studentId, int $limit = 10): array
    {
        try {
            // 从knowledge_point_mastery_snapshots表获取快照
            $snapshots = \DB::table('knowledge_point_mastery_snapshots')
                ->where('student_id', $studentId)
                ->orderBy('created_at', 'desc')
                ->limit($limit)
                ->get();

            $snapshotList = $snapshots->map(function ($snapshot) {
                // 解析掌握度数据
                $masteryData = json_decode($snapshot->mastery_data, true) ?: [];

                // 提取知识点信息 - 修复字段名
                $knowledgePoints = [];
                $parentKnowledgePoints = []; // 存储父知识点信息
                $kpCodes = array_keys($masteryData); // 收集所有kp_code用于批量获取名称

                // 批量获取知识点名称
                $kpNamesMap = $this->getKnowledgePointNamesMap($kpCodes);

                // 第一步：分类父知识点和子知识点
                foreach ($masteryData as $kpCode => $kpData) {
                    $isParent = (bool) ($kpData['is_parent'] ?? false);
                    $masteryLevel = floatval($kpData['current_mastery'] ?? 0);
                    $change = floatval($kpData['change'] ?? 0);
                    $weight = intval($kpData['weight'] ?? 1);

                    if ($isParent) {
                        // 父知识点 - 稍后重新计算
                        $parentKnowledgePoints[$kpCode] = [
                            'kp_code' => $kpCode,
                            'kp_name' => $kpNamesMap[$kpCode] ?? $kpCode,
                            'original_mastery' => $masteryLevel,
                            'change' => $change,
                            'weight' => $weight,
                            'children' => [] // 存储子知识点
                        ];
                    } else {
                        // 子知识点 - 直接添加
                        $knowledgePoints[] = [
                            'kp_code' => $kpCode,
                            'kp_name' => $kpNamesMap[$kpCode] ?? $kpCode,
                            'mastery_level' => round($masteryLevel, 2),
                            'change' => round($change, 2),
                            'is_child' => true,
                            'parent_code' => null, // 稍后填入父知识点
                        ];
                    }
                }

                // 第二步：建立父子关系并计算父知识点掌握度
                foreach ($masteryData as $kpCode => $kpData) {
                    $isParent = (bool) ($kpData['is_parent'] ?? false);

                    if (!$isParent) {
                        // 查找父知识点（通过代码前缀匹配或其他逻辑）
                        foreach ($parentKnowledgePoints as $parentCode => $parentData) {
                            // 简单的父子关系判断：如果子知识点代码包含父知识点代码前缀
                            if (strpos($kpCode, $parentCode) === 0 || $this->isChildOf($kpCode, $parentCode)) {
                                // 添加到父知识点的子知识点列表
                                $parentKnowledgePoints[$parentCode]['children'][] = $kpCode;

                                // 更新子知识点的父知识点信息
                                foreach ($knowledgePoints as &$child) {
                                    if ($child['kp_code'] === $kpCode) {
                                        $child['parent_code'] = $parentCode;
                                        break;
                                    }
                                }
                                break;
                            }
                        }
                    }
                }

                // 第三步：计算父知识点的掌握度（加权平均）
                foreach ($parentKnowledgePoints as $parentCode => &$parentData) {
                    if (empty($parentData['children'])) {
                        // 如果没有子知识点，使用原始值
                        $parentData['mastery_level'] = round($parentData['original_mastery'], 2);
                    } else {
                        // 计算子知识点的加权平均
                        $totalWeightedMastery = 0;
                        $totalWeight = 0;

                        foreach ($parentData['children'] as $childCode) {
                            if (isset($masteryData[$childCode])) {
                                $childMastery = floatval($masteryData[$childCode]['current_mastery'] ?? 0);
                                $childWeight = intval($masteryData[$childCode]['weight'] ?? 1);
                                $totalWeightedMastery += $childMastery * $childWeight;
                                $totalWeight += $childWeight;
                            }
                        }

                        if ($totalWeight > 0) {
                            $parentData['mastery_level'] = round($totalWeightedMastery / $totalWeight, 2);
                            // 重新计算变化值
                            $parentData['change'] = round($parentData['mastery_level'] - $parentData['original_mastery'], 2);
                        } else {
                            $parentData['mastery_level'] = round($parentData['original_mastery'], 2);
                        }
                    }

                    $parentData['is_parent'] = true;
                    unset($parentData['original_mastery']); // 移除临时字段

                    // 添加到知识点列表
                    $knowledgePoints[] = $parentData;
                }
                unset($parentData); // 避免引用问题

                // 第四步：按知识点代码排序
                usort($knowledgePoints, function($a, $b) {
                    return strcmp($a['kp_code'], $b['kp_code']);
                });

                return [
                    'snapshot_id' => $snapshot->snapshot_id,
                    'student_id' => $snapshot->student_id,
                    'paper_id' => $snapshot->paper_id,
                    'overall_mastery' => floatval($snapshot->overall_mastery),
                    'weak_knowledge_points_count' => intval($snapshot->weak_knowledge_points_count),
                    'strong_knowledge_points_count' => intval($snapshot->strong_knowledge_points_count),
                    'knowledge_points' => $knowledgePoints,
                    'knowledge_points_count' => count($knowledgePoints),
                    'created_at' => $snapshot->created_at,
                    'snapshot_time' => $snapshot->snapshot_time,
                ];
            })->toArray();

            Log::info('KnowledgeMasteryService::getGraphSnapshots (Local)', [
                'student_id' => $studentId,
                'limit' => $limit,
                'snapshot_count' => count($snapshotList)
            ]);
            return [
                'success' => true,
                'data' => [
                    'snapshots' => $snapshotList,
                    'total' => count($snapshotList),
                ],
            ];
        } catch (\Throwable $e) {
            Log::error('Knowledge graph snapshots exception', [
                'student_id' => $studentId,
                'limit' => $limit,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'error' => '获取知识点图谱快照列表异常: ' . $e->getMessage(),
            ];
        }
    }

    /**
     * 获取学生知识点掌握摘要（简化版）
     *
     * @param string $studentId 学生ID
     * @return array
     */
    public function getSummary(string $studentId): array
    {
        $stats = $this->getStats($studentId);

        if (!$stats['success']) {
            return $stats;
        }

        $data = $stats['data'];

        return [
            'success' => true,
            'data' => [
                'student_id' => $data['student_id'] ?? $studentId,
                'total' => $data['total_knowledge_points'] ?? 0,
                'mastered' => $data['mastered_knowledge_points'] ?? 0,
                'unmastered' => $data['unmastered_knowledge_points'] ?? 0,
                'mastery_rate' => $data['mastery_rate'] ?? 0.0,
                'mastery_percentage' => round(($data['mastery_rate'] ?? 0) * 100, 1) . '%',
                'graph_total' => $data['graph_total_knowledge_points'] ?? 0,
            ],
        ];
    }

    /**
     * 创建知识点掌握度快照
     *
     * @param string $studentId 学生ID
     * @param string $snapshotType 快照类型 (exam/report/manual/scheduled)
     * @param string|null $sourceId 来源ID
     * @param string|null $sourceName 来源名称
     * @param string|null $notes 备注
     * @return array
     */
    public function createSnapshot(
        string $studentId,
        string $snapshotType = 'report',
        ?string $sourceId = null,
        ?string $sourceName = null,
        ?string $notes = null
    ): array {
        try {
            // 使用LocalAIAnalysisService创建快照
            $localAI = app(LocalAIAnalysisService::class);

            // 获取当前掌握度数据
            $masteryCalculator = app(MasteryCalculator::class);
            $overview = $masteryCalculator->getStudentMasteryOverview($studentId);

            $snapshots = [];
            foreach ($overview['details'] as $detail) {
                $snapshotId = \DB::table('knowledge_point_mastery_snapshots')->insertGetId([
                    'student_id' => $studentId,
                    'kp_code' => $detail->kp_code,
                    'mastery_level' => $detail->mastery_level,
                    'confidence_level' => $detail->confidence_level,
                    'snapshot_type' => $snapshotType,
                    'source_id' => $sourceId,
                    'source_name' => $sourceName,
                    'notes' => $notes,
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);

                $snapshots[] = [
                    'snapshot_id' => $snapshotId,
                    'kp_code' => $detail->kp_code,
                    'mastery_level' => $detail->mastery_level,
                ];
            }

            Log::info('KnowledgeMasteryService::createSnapshot (Local)', [
                'student_id' => $studentId,
                'snapshot_type' => $snapshotType,
                'snapshot_count' => count($snapshots),
            ]);

            return [
                'success' => true,
                'data' => [
                    'snapshots' => $snapshots,
                    'total_snapshots' => count($snapshots),
                ],
            ];
        } catch (\Throwable $e) {
            Log::error('Create knowledge mastery snapshot exception', [
                'student_id' => $studentId,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'error' => '创建知识点掌握度快照异常: ' . $e->getMessage(),
            ];
        }
    }
}
