<?php

namespace App\Services;

use App\Models\MistakeRecord;
use App\Models\Student;
use App\Models\Teacher;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;

class MistakeBookService
{
    protected string $learningAnalyticsBase;
    protected int $timeout;

    // 缓存时间（秒）
    const CACHE_TTL_SUMMARY = 600; // 10分钟
    const CACHE_TTL_PATTERNS = 1800; // 30分钟

    public function __construct(
        ?string $learningAnalyticsBase = null,
        ?int $timeout = null
    ) {
        // 已迁移到本地，不再使用LearningAnalytics
        $this->learningAnalyticsBase = '';
        $this->timeout = 20;
    }

    /**
     * 新增错题
     */
    public function createMistake(array $payload): array
    {
        $studentId = $payload['student_id'] ?? null;
        $questionId = $payload['question_id'] ?? null;
        $paperId = $payload['paper_id'] ?? null;
        $myAnswer = $payload['my_answer'] ?? null;
        $correctAnswer = $payload['correct_answer'] ?? null;
        $questionText = $payload['question_text'] ?? null;
        $knowledgePoint = $payload['knowledge_point'] ?? null;
        $explanation = $payload['explanation'] ?? null;
        $kpIds = $payload['kp_ids'] ?? null;
        $source = $payload['source'] ?? MistakeRecord::SOURCE_PRACTICE;
        $happenedAt = $payload['happened_at'] ?? now();

        if (!$studentId) {
            throw new \InvalidArgumentException('学生ID不能为空');
        }

        // 使用事务确保数据一致性
        return \DB::transaction(function () use (
            $studentId, $questionId, $paperId, $myAnswer, $correctAnswer,
            $questionText, $knowledgePoint, $explanation, $kpIds, $source, $happenedAt
        ) {
            // 【修复】检查是否已存在相同错题（避免重复）
            // 重复定义：同一学生 + 同一题目 + 同一卷子 的组合
            // 这样允许同一题目在不同卷子中重复，也允许同一卷子中的新题目被记录
            $query = MistakeRecord::where('student_id', $studentId)
                ->where('source', $source);

            // 如果有 question_id 和 paper_id，用它们去重
            // 否则用 question_text 去重
            if ($questionId && $paperId) {
                $query->where('question_id', $questionId)
                      ->where('paper_id', $paperId);
                Log::debug('错题记录重复检查', [
                    'student_id' => $studentId,
                    'question_id' => $questionId,
                    'paper_id' => $paperId,
                    'check_type' => 'question_id + paper_id'
                ]);
            } elseif ($questionId) {
                $query->where('question_id', $questionId);
                Log::debug('错题记录重复检查', [
                    'student_id' => $studentId,
                    'question_id' => $questionId,
                    'check_type' => 'question_id only'
                ]);
            } elseif ($questionText) {
                $query->where('question_text', $questionText);
                Log::debug('错题记录重复检查', [
                    'student_id' => $studentId,
                    'question_text' => substr($questionText, 0, 50) . '...',
                    'check_type' => 'question_text'
                ]);
            } else {
                Log::warning('错题记录保存失败：缺少题目ID和题目文本', [
                    'student_id' => $studentId,
                    'paper_id' => $paperId
                ]);
                return [
                    'duplicate' => false,
                    'error' => '缺少题目ID和题目文本，无法创建错题记录'
                ];
            }

            $existingMistake = $query->first();

            if ($existingMistake) {
                Log::debug('发现重复错题记录，合并知识点', [
                    'student_id' => $studentId,
                    'question_id' => $questionId,
                    'paper_id' => $paperId,
                    'existing_mistake_id' => $existingMistake->id
                ]);

                // 合并知识点到已有记录中
                $updates = ['updated_at' => now()];
                if ($kpIds) {
                    $existingKpIds = $existingMistake->kp_ids ?? [];
                    $newKpIds = is_array($kpIds) ? $kpIds : [$kpIds];

                    // 合并并去重
                    $mergedKpIds = array_values(array_unique(array_merge($existingKpIds, $newKpIds)));

                    // 更新记录（仅更新 kp_ids）
                    $updates['kp_ids'] = $mergedKpIds;

                    Log::info('错题记录知识点合并成功', [
                        'student_id' => $studentId,
                        'question_id' => $questionId,
                        'paper_id' => $paperId,
                        'existing_kp_ids' => $existingKpIds,
                        'new_kp_ids' => $newKpIds,
                        'merged_kp_ids' => $mergedKpIds
                    ]);
                }

                $existingMistake->update($updates);

                return [
                    'duplicate' => true,
                    'mistake_id' => $existingMistake->id,
                    'message' => '错题已存在，已合并知识点',
                ];
            }

            // 创建错题记录（合并知识点到数组）
            $mistake = MistakeRecord::create([
                'student_id' => $studentId,
                'question_id' => $questionId,
                'paper_id' => $paperId,
                'student_answer' => $myAnswer,
                'correct_answer' => $correctAnswer,
                'question_text' => $questionText,
                'knowledge_point' => $knowledgePoint,
                'explanation' => $explanation,
                'kp_ids' => is_array($kpIds) ? $kpIds : ($kpIds ? [$kpIds] : null), // 确保是数组
                'source' => $source,
                'created_at' => $happenedAt,
                'review_status' => MistakeRecord::REVIEW_STATUS_PENDING,
                'review_count' => 0,
            ]);

            // 清除相关缓存
            $this->clearCache($studentId);

            return [
                'duplicate' => false,
                'mistake_id' => $mistake->id,
                'created_at' => $mistake->created_at,
            ];
        });
    }

    /**
     * 批量新增错题（同一学生/卷子）
     *
     * @param array<int, array> $payloads
     * @return array
     */
    public function createMistakesBatch(array $payloads): array
    {
        if (empty($payloads)) {
            return ['created' => 0, 'duplicates' => 0, 'updated' => 0];
        }

        $studentId = $payloads[0]['student_id'] ?? null;
        $paperId = $payloads[0]['paper_id'] ?? null;
        $source = $payloads[0]['source'] ?? MistakeRecord::SOURCE_PRACTICE;

        if (!$studentId) {
            throw new \InvalidArgumentException('学生ID不能为空');
        }

        $questionIds = [];
        foreach ($payloads as $payload) {
            if (!empty($payload['question_id'])) {
                $questionIds[] = $payload['question_id'];
            }
        }

        $questionIds = array_values(array_unique($questionIds));

        return \DB::transaction(function () use ($payloads, $studentId, $paperId, $source, $questionIds) {
            $existingMap = [];
            if (!empty($questionIds)) {
                $existing = MistakeRecord::where('student_id', $studentId)
                    ->where('source', $source)
                    ->when($paperId, fn ($q) => $q->where('paper_id', $paperId))
                    ->whereIn('question_id', $questionIds)
                    ->get();

                foreach ($existing as $item) {
                    $existingMap[$item->question_id] = $item;
                }
            }

            $toInsert = [];
            $created = 0;
            $duplicates = 0;
            $updated = 0;

            foreach ($payloads as $payload) {
                $questionId = $payload['question_id'] ?? null;
                if (!$questionId) {
                    continue;
                }

                $kpIds = $payload['kp_ids'] ?? null;
                $kpIds = is_array($kpIds) ? $kpIds : ($kpIds ? [$kpIds] : null);

                if (isset($existingMap[$questionId])) {
                    $duplicates++;
                    $updates = ['updated_at' => now()];
                    if ($kpIds) {
                        $existingKpIds = $existingMap[$questionId]->kp_ids ?? [];
                        $merged = array_values(array_unique(array_merge($existingKpIds, $kpIds)));
                        if ($merged !== $existingKpIds) {
                            $updates['kp_ids'] = $merged;
                            $updated++;
                        }
                    }
                    $existingMap[$questionId]->update($updates);
                    continue;
                }

                $toInsert[] = [
                    'student_id' => $studentId,
                    'question_id' => $questionId,
                    'paper_id' => $payload['paper_id'] ?? null,
                    'student_answer' => $payload['my_answer'] ?? null,
                    'correct_answer' => $payload['correct_answer'] ?? null,
                    'question_text' => $payload['question_text'] ?? null,
                    'knowledge_point' => $payload['knowledge_point'] ?? null,
                    'explanation' => $payload['explanation'] ?? null,
                    'kp_ids' => $kpIds ? json_encode($kpIds, JSON_UNESCAPED_UNICODE) : null,
                    'source' => $payload['source'] ?? MistakeRecord::SOURCE_PRACTICE,
                    'created_at' => $payload['happened_at'] ?? now(),
                    'review_status' => MistakeRecord::REVIEW_STATUS_PENDING,
                    'review_count' => 0,
                ];
            }

            if (!empty($toInsert)) {
                // MistakeRecord::insert 不会触发模型事件，但速度更快
                MistakeRecord::insert($toInsert);
                $created = count($toInsert);
            }

            // 统一刷新本次题目的 updated_at（无论是否合并）
            if (!empty($questionIds)) {
                \DB::table('mistake_records')
                    ->where('student_id', $studentId)
                    ->where('source', $source)
                    ->when($paperId, fn ($q) => $q->where('paper_id', $paperId))
                    ->whereIn('question_id', $questionIds)
                    ->update(['updated_at' => now()]);
            }

            $this->clearCache($studentId);

            return [
                'created' => $created,
                'duplicates' => $duplicates,
                'updated' => $updated,
            ];
        });
    }

    /**
     * 获取错题列表
     */
    public function listMistakes(array $params = []): array
    {
        $studentId = $params['student_id'] ?? null;
        $page = (int) ($params['page'] ?? 1);
        $perPage = (int) ($params['per_page'] ?? 20);

        if (!$studentId) {
            return [
                'data' => [],
                'meta' => ['total' => 0, 'page' => $page, 'per_page' => $perPage],
                'statistics' => [  // ✅ 无 student_id 时也返回空统计
                    'total' => 0,
                    'pending' => 0,
                    'reviewed' => 0,
                    'mastered' => 0,
                    'favorites' => 0,
                    'in_retry_list' => 0,
                    'this_week' => 0,
                    'mastery_rate' => 0.0,
                ],
            ];
        }

        try {
            $query = MistakeRecord::forStudent($studentId)
                ->with(['student']) // 预加载学生信息
                ->orderByDesc('created_at');

            // 应用筛选条件
            $this->applyFilters($query, $params);

            // 获取总数
            $total = $query->count();

            // 分页获取数据
            $mistakes = $query->skip(($page - 1) * $perPage)
                ->take($perPage)
                ->get();

            // 转换数据格式
            $data = $mistakes->map(function ($mistake) {
                return $this->transformMistakeRecord($mistake, false);
            })->toArray();

            // 获取统计信息
            $summary = $this->summarize($studentId);

            return [
                'data' => $data,
                'meta' => [
                    'total' => $total,
                    'page' => $page,
                    'per_page' => $perPage,
                    'last_page' => (int) ceil($total / $perPage),
                ],
                'statistics' => $summary,
            ];

        } catch (\Throwable $e) {
            Log::error('获取错题列表失败', [
                'student_id' => $studentId,
                'error' => $e->getMessage(),
                'params' => $params,
            ]);

            return [
                'data' => [],
                'meta' => ['total' => 0, 'page' => $page, 'per_page' => $perPage],
                'statistics' => [  // ✅ 错误时也返回空统计
                    'total' => 0,
                    'pending' => 0,
                    'reviewed' => 0,
                    'mastered' => 0,
                    'favorites' => 0,
                    'in_retry_list' => 0,
                    'this_week' => 0,
                    'mastery_rate' => 0.0,
                ],
            ];
        }
    }

    /**
     * 获取错题详情
     */
    public function getMistakeDetail(string $mistakeId, ?string $studentId = null): array
    {
        try {
            $query = MistakeRecord::with(['student']);

            if ($studentId) {
                $query->forStudent($studentId);
            }

            $mistake = $query->find($mistakeId);

            if (!$mistake) {
                return [];
            }

            return $this->transformMistakeRecord($mistake, true);

        } catch (\Throwable $e) {
            Log::error('获取错题详情失败', [
                'mistake_id' => $mistakeId,
                'student_id' => $studentId,
                'error' => $e->getMessage(),
            ]);

            return [];
        }
    }

    /**
     * 获取错题统计概要
     */
    public function summarize(string $studentId): array
    {
        $cacheKey = "mistake_book:summary:{$studentId}";

        return Cache::remember($cacheKey, self::CACHE_TTL_SUMMARY, function () use ($studentId) {
            return MistakeRecord::getSummary($studentId);
        });
    }

    /**
     * 获取错误模式分析
     */
    public function getMistakePatterns(string $studentId): array
    {
        $cacheKey = "mistake_book:patterns:{$studentId}";

        return Cache::remember($cacheKey, self::CACHE_TTL_PATTERNS, function () use ($studentId) {
            return MistakeRecord::getMistakePatterns($studentId);
        });
    }

    /**
     * 收藏/取消收藏错题
     */
    public function toggleFavorite(string $mistakeId, bool $favorite = true): bool
    {
        try {
            $mistake = MistakeRecord::find($mistakeId);
            if (!$mistake) {
                return false;
            }

            $mistake->update(['is_favorite' => $favorite]);

            // 清除缓存
            $this->clearCache($mistake->student_id);

            return true;

        } catch (\Throwable $e) {
            Log::error('收藏错题失败', [
                'mistake_id' => $mistakeId,
                'favorite' => $favorite,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * 标记已复习
     */
    public function markReviewed(string $mistakeId): bool
    {
        try {
            $mistake = MistakeRecord::find($mistakeId);
            if (!$mistake) {
                return false;
            }

            $mistake->markAsReviewed();

            // 清除缓存
            $this->clearCache($mistake->student_id);

            return true;

        } catch (\Throwable $e) {
            Log::error('标记已复习失败', [
                'mistake_id' => $mistakeId,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * 修改复习状态
     */
    public function updateReviewStatus(string $mistakeId, string $action = 'increment', bool $forceReview = false): array
    {
        try {
            $mistake = MistakeRecord::find($mistakeId);
            if (!$mistake) {
                return [
                    'success' => false,
                    'error' => '错题记录不存在',
                ];
            }

            match ($action) {
                'increment' => $mistake->markAsReviewed(),
                'mastered' => $mistake->markAsMastered(),
                'reset' => $mistake->update([
                    'review_status' => MistakeRecord::REVIEW_STATUS_PENDING,
                    'review_count' => 0,
                    'mastery_level' => null,
                    'reviewed_at' => null,
                    'next_review_at' => null,
                ]),
                default => throw new \InvalidArgumentException('无效的操作类型'),
            };

            // 重新加载模型数据以获取最新状态
            $mistake->refresh();

            return [
                'success' => true,
                'mistake_id' => $mistakeId,
                'review_status' => $mistake->review_status,
                'review_count' => $mistake->review_count,
                'reviewed_at' => $mistake->reviewed_at?->toISOString(),
                'next_review_at' => $mistake->next_review_at?->toISOString(),
                'mastery_level' => $mistake->mastery_level,
                'message' => '复习状态更新成功',
            ];

        } catch (\Throwable $e) {
            Log::error('更新复习状态失败', [
                'mistake_id' => $mistakeId,
                'action' => $action,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * 获取复习状态
     */
    public function getReviewStatus(string $mistakeId): array
    {
        try {
            $mistake = MistakeRecord::find($mistakeId);
            if (!$mistake) {
                return [
                    'success' => false,
                    'error' => '错题记录不存在',
                ];
            }

            return [
                'success' => true,
                'mistake_id' => $mistakeId,
                'review_status' => $mistake->review_status,
                'review_count' => $mistake->review_count,
                'reviewed_at' => $mistake->reviewed_at?->toISOString(),
                'next_review_at' => $mistake->next_review_at?->toISOString(),
                'mastery_level' => $mistake->mastery_level,
                'force_review' => $mistake->force_review,
            ];

        } catch (\Throwable $e) {
            Log::error('获取复习状态失败', [
                'mistake_id' => $mistakeId,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * 增加复习次数
     */
    public function incrementReviewCount(string $mistakeId, bool $forceReview = false): array
    {
        return $this->updateReviewStatus($mistakeId, 'increment', $forceReview);
    }

    /**
     * 重置为强制复习状态
     */
    public function resetReviewStatus(string $mistakeId): array
    {
        return $this->updateReviewStatus($mistakeId, 'reset');
    }

    /**
     * 添加到重练清单
     */
    public function addToRetryList(string $mistakeId): bool
    {
        try {
            $mistake = MistakeRecord::find($mistakeId);
            if (!$mistake) {
                return false;
            }

            $mistake->addToRetryList();

            // 清除缓存
            $this->clearCache($mistake->student_id);

            return true;

        } catch (\Throwable $e) {
            Log::error('加入重练清单失败', [
                'mistake_id' => $mistakeId,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * 批量操作错题
     */
    public function batchOperation(array $mistakeIds, string $operation, array $params = []): array
    {
        if (empty($mistakeIds)) {
            return [
                'success' => false,
                'error' => '请选择要操作的错题',
            ];
        }

        try {
            $mistakes = MistakeRecord::whereIn('id', $mistakeIds)->get();
            $successCount = 0;
            $errors = [];

            foreach ($mistakes as $mistake) {
                try {
                    match ($operation) {
                        'favorite' => $mistake->toggleFavorite(),
                        'reviewed' => $mistake->markAsReviewed(),
                        'mastered' => $mistake->markAsMastered(),
                        'retry_list' => $mistake->addToRetryList(),
                        'remove_retry_list' => $mistake->removeFromRetryList(),
                        'set_error_type' => $mistake->update(['error_type' => $params['error_type'] ?? null]),
                        'set_importance' => $mistake->update(['importance' => $params['importance'] ?? 5]),
                        default => throw new \InvalidArgumentException('不支持的操作'),
                    };

                    $successCount++;
                } catch (\Throwable $e) {
                    $errors[] = [
                        'mistake_id' => $mistake->id,
                        'error' => $e->getMessage(),
                    ];
                }
            }

            // 清除缓存
            if ($successCount > 0) {
                $studentIds = $mistakes->pluck('student_id')->unique();
                foreach ($studentIds as $studentId) {
                    $this->clearCache($studentId);
                }
            }

            return [
                'success' => true,
                'total' => count($mistakeIds),
                'success_count' => $successCount,
                'error_count' => count($errors),
                'errors' => $errors,
            ];

        } catch (\Throwable $e) {
            Log::error('批量操作失败', [
                'operation' => $operation,
                'mistake_ids' => $mistakeIds,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * 基于错题推荐练习题（本地实现）
     */
    public function recommendPractice(string $studentId, array $kpIds = [], array $skillIds = []): array
    {
        try {
            // 获取学生未掌握的知识点
            $weakKnowledgePoints = MistakeRecord::forStudent($studentId)
                ->where('review_status', '!=', MistakeRecord::REVIEW_STATUS_MASTERED)
                ->pluck('knowledge_point')
                ->filter()
                ->unique()
                ->values()
                ->toArray();

            // 合并传入的知识点
            $allKpIds = array_unique(array_merge($kpIds, $weakKnowledgePoints));

            // TODO: 这里应该调用本地题库服务
            // 目前返回模拟数据
            $recommendations = [];
            foreach (array_slice($allKpIds, 0, 5) as $kpId) {
                $recommendations[] = [
                    'id' => "rec_{$kpId}_{$studentId}",
                    'kp_code' => $kpId,
                    'question_text' => "针对知识点 {$kpId} 的练习题",
                    'difficulty' => 0.5,
                    'source' => 'recommendation',
                ];
            }

            return ['data' => $recommendations];

        } catch (\Throwable $e) {
            Log::error('推荐练习题失败', [
                'student_id' => $studentId,
                'error' => $e->getMessage(),
            ]);

            return ['data' => []];
        }
    }

    /**
     * 获取仪表板快照数据
     */
    public function getPanelSnapshot(string $studentId, int $limit = 5): array
    {
        try {
            $recentMistakes = MistakeRecord::forStudent($studentId)
                ->orderByDesc('created_at')
                ->limit($limit)
                ->get()
                ->map(fn($m) => $this->transformMistakeRecord($m))
                ->toArray();

            $patterns = $this->getMistakePatterns($studentId);
            $summary = $this->summarize($studentId);

            return [
                'recent' => $recentMistakes,
                'weak_skills' => array_slice($patterns['error_types'] ?? [], 0, 5, true),
                'weak_kps' => array_slice($patterns['knowledge_points'] ?? [], 0, 5, true),
                'error_types' => $patterns['error_types'] ?? [],
                'stats' => $summary,
            ];

        } catch (\Throwable $e) {
            Log::error('获取快照数据失败', [
                'student_id' => $studentId,
                'error' => $e->getMessage(),
            ]);

            return [
                'recent' => [],
                'weak_skills' => [],
                'weak_kps' => [],
                'error_types' => [],
                'stats' => [
                    'total' => 0,
                    'pending' => 0,
                    'this_week' => 0,
                ],
            ];
        }
    }

    /**
     * 应用筛选条件
     */
    private function applyFilters($query, array $params): void
    {
        // 知识点筛选
        if (!empty($params['kp_ids'])) {
            $kpIds = is_array($params['kp_ids']) ? $params['kp_ids'] : explode(',', $params['kp_ids']);
            $query->byKnowledgePoint($kpIds);
        }

        // 技能筛选
        if (!empty($params['skill_ids'])) {
            $skillIds = is_array($params['skill_ids']) ? $params['skill_ids'] : explode(',', $params['skill_ids']);
            $query->where(function ($q) use ($skillIds) {
                foreach ($skillIds as $skillId) {
                    $q->orWhereJsonContains('skill_ids', $skillId);
                }
            });
        }

        // 错误类型筛选
        if (!empty($params['error_types'])) {
            $errorTypes = is_array($params['error_types']) ? $params['error_types'] : explode(',', $params['error_types']);
            $query->whereIn('error_type', $errorTypes);
        }

        // 时间范围筛选
        if (!empty($params['time_range'])) {
            match ($params['time_range']) {
                'last_7' => $query->where('created_at', '>=', now()->subDays(7)),
                'last_30' => $query->where('created_at', '>=', now()->subDays(30)),
                'last_90' => $query->where('created_at', '>=', now()->subDays(90)),
                default => null,
            };
        }

        // 自定义时间范围
        if (!empty($params['start_date'])) {
            $query->whereDate('created_at', '>=', $params['start_date']);
        }
        if (!empty($params['end_date'])) {
            $query->whereDate('created_at', '<=', $params['end_date']);
        }

        // 复习状态筛选
        if (!empty($params['unreviewed_only'])) {
            $query->pending();
        }
        if (!empty($params['favorite_only'])) {
            $query->favorites();
        }
        if (!empty($params['in_retry_list_only'])) {
            $query->inRetryList();
        }

        // 排序
        $sortBy = $params['sort_by'] ?? 'created_at_desc';
        match ($sortBy) {
            'created_at_asc' => $query->orderBy('created_at'),
            'created_at_desc' => $query->orderByDesc('created_at'),
            'review_status_asc' => $query->orderBy('review_status'),
            'difficulty_desc' => $query->orderByDesc('difficulty'),
            default => null,
        };
    }

    /**
     * 转换错题记录格式
     */
    private function transformMistakeRecord(MistakeRecord $mistake, bool $detailed = false): array
    {
        // 【新增】通过 question_id 关联获取题目详情
        $questionDetails = $this->getQuestionDetails($mistake->question_id);

        // 【新增】通过 kp_ids 或 textbook_catalog_nodes_id 获取知识点信息
        $knowledgePoints = $this->getKnowledgePoints(
            $mistake->kp_ids,
            $mistake->question_id,
            $questionDetails['textbook_catalog_nodes_id'] ?? null
        );

        $data = [
            // ========== 错题记录基本信息 ==========
            'id' => $mistake->id,
            'student_id' => $mistake->student_id,
            'question_id' => $mistake->question_id,
            'paper_id' => $mistake->paper_id,
            'created_at' => $mistake->created_at?->toISOString(),
            'review_status' => $mistake->review_status,
            'review_status_label' => $mistake->review_status_label,
            'review_count' => $mistake->review_count,
            'is_favorite' => $mistake->is_favorite,
            'in_retry_list' => $mistake->in_retry_list,
            'reviewed_at' => $mistake->reviewed_at?->toISOString(),
            'next_review_at' => $mistake->next_review_at?->toISOString(),
            'error_type' => $mistake->error_type,
            'error_type_label' => $mistake->error_type_label,
            'explanation' => $mistake->explanation,
            'skill_ids' => $mistake->skill_ids,
            'difficulty' => $mistake->difficulty,
            'difficulty_level' => $mistake->difficulty_level,
            'importance' => $mistake->importance,
            'mastery_level' => $mistake->mastery_level,

            // ========== 题目信息（优先呈现）==========
            // 题目内容：优先使用 questions.stem，其次使用错题本自带
            'question_text' => $questionDetails['stem'] ?? $mistake->question_text,
            // 答案：优先使用 questions.answer，其次使用错题本自带
            'correct_answer' => $questionDetails['answer'] ?? $mistake->correct_answer,
            // 解题过程/解析：优先使用 questions.solution
            'solution' => $questionDetails['solution'] ?? $mistake->explanation,
            // 选项
            'options' => $questionDetails['options'] ?? null,
            // 题目类型
            'question_type' => $questionDetails['question_type'] ?? null,
            // 题目难度（从题目表获取）
            'question_difficulty' => $questionDetails['difficulty'] ?? null,
            // 题目标签
            'question_tags' => $questionDetails['tags'] ?? null,
            // 题目来源
            'question_source' => $questionDetails['source'] ?? null,

            // 学生答案（始终使用错题本中的记录）
            'student_answer' => $mistake->student_answer,

            // ========== 知识点信息 ==========
            'knowledge_points' => $knowledgePoints,
        ];

        if ($detailed) {
            $data['student'] = [
                'id' => $mistake->student?->student_id,
                'name' => $mistake->student?->name,
                'grade' => $mistake->student?->grade,
                'class_name' => $mistake->student?->class_name,
            ];
        }

        return $data;
    }

    /**
     * 清除缓存
     */
    private function clearCache(string|int $studentId): void
    {
        try {
            $patterns = [
                "mistake_book:summary:{$studentId}",
                "mistake_book:patterns:{$studentId}",
            ];

            foreach ($patterns as $key) {
                Cache::forget($key);
            }
        } catch (\Exception $e) {
            // 缓存清除失败不影响主流程
            Log::debug('缓存清除失败（可忽略）', ['error' => $e->getMessage()]);
        }
    }

    /**
     * 【新增】通过 question_id 获取题目详情
     */
    private function getQuestionDetails(?string $questionId): ?array
    {
        if (!$questionId) {
            return null;
        }

        try {
            $question = \DB::connection('mysql')
                ->table('questions')
                ->where('id', $questionId)
                ->first();

            if (!$question) {
                return null;
            }

            return [
                'stem' => $question->stem ?? null,  // 题目内容（题干）
                'options' => $question->options ?? null,  // 选项
                'answer' => $question->answer ?? null,  // 答案
                'solution' => $question->solution ?? null,  // 解题过程/解析
                'difficulty' => $question->difficulty ?? null,
                'question_type' => $question->question_type ?? null,
                'textbook_catalog_nodes_id' => $question->textbook_catalog_nodes_id ?? null,
                'tags' => $question->tags ?? null,  // 标签
                'source' => $question->source ?? null,  // 来源
            ];
        } catch (\Exception $e) {
            Log::warning('获取题目详情失败', [
                'question_id' => $questionId,
                'error' => $e->getMessage()
            ]);
            return null;
        }
    }

    /**
     * 【新增】通过 kp_ids 或 textbook_catalog_nodes_id 获取知识点信息
     *
     * 逻辑：
     * 1. 如果有 kp_ids，直接从 knowledge_points 表查询
     * 2. 如果没有 kp_ids，通过 textbook_catalog_nodes_id 关联 textbook_chapter_knowledge_relation 表获取 kp_id
     */
    private function getKnowledgePoints(?array $kpIds, ?string $questionId = null, ?int $catalogNodesId = null): array
    {
        // 如果有 kp_ids，直接查询
        if (!empty($kpIds)) {
            return $this->queryKnowledgePointsByCodes($kpIds);
        }

        // 如果没有 kp_ids，通过题目ID和目录节点ID关联查询
        if ($questionId || $catalogNodesId) {
            $kpCodesFromRelation = $this->getKpCodesFromRelation($questionId, $catalogNodesId);
            if (!empty($kpCodesFromRelation)) {
                return $this->queryKnowledgePointsByCodes($kpCodesFromRelation);
            }
        }

        return [];
    }

    /**
     * 通过 kp_codes 查询知识点信息
     */
    private function queryKnowledgePointsByCodes(array $kpCodes): array
    {
        try {
            $knowledgePoints = \DB::connection('mysql')
                ->table('knowledge_points')
                ->whereIn('kp_code', $kpCodes)
                ->select(['kp_code', 'name', 'parent_kp_code'])
                ->get()
                ->toArray();

            return array_map(function ($kp) {
                return [
                    'kp_code' => $kp->kp_code,
                    'name' => $kp->name ?? $kp->kp_code,
                    'parent_kp_code' => $kp->parent_kp_code,
                ];
            }, $knowledgePoints);
        } catch (\Exception $e) {
            Log::warning('通过kp_codes获取知识点信息失败', [
                'kp_codes' => $kpCodes,
                'error' => $e->getMessage()
            ]);
            return [];
        }
    }

    /**
     * 通过 textbook_catalog_nodes_id 关联 textbook_chapter_knowledge_relation 表获取 kp_codes
     */
    private function getKpCodesFromRelation(?string $questionId, ?int $catalogNodesId): array
    {
        try {
            $query = \DB::connection('mysql')
                ->table('textbook_chapter_knowledge_relation')
                ->where('is_deleted', 0);

            if ($catalogNodesId) {
                $query->where('catalog_chapter_id', $catalogNodesId);
            } elseif ($questionId) {
                // 如果没有catalog_nodes_id，尝试从questions表获取
                $question = \DB::connection('mysql')
                    ->table('questions')
                    ->where('id', $questionId)
                    ->first();

                if ($question && $question->textbook_catalog_nodes_id) {
                    $query->where('catalog_chapter_id', $question->textbook_catalog_nodes_id);
                }
            }

            $relations = $query->select('kp_code')->get();

            if ($relations->isNotEmpty()) {
                Log::debug('通过目录节点关联获取到知识点', [
                    'question_id' => $questionId,
                    'catalog_nodes_id' => $catalogNodesId,
                    'kp_codes' => $relations->pluck('kp_code')->toArray()
                ]);
            }

            return $relations->pluck('kp_code')->toArray();
        } catch (\Exception $e) {
            Log::warning('通过目录节点关联获取kp_codes失败', [
                'question_id' => $questionId,
                'catalog_nodes_id' => $catalogNodesId,
                'error' => $e->getMessage()
            ]);
            return [];
        }
    }
}
