import { apiDelete, apiFetch } from "@/lib/api/client"; export type LearningTask = { id: string; study_plan_id: string; daily_plan_id?: string | null; logical_key?: string | null; subject_id: string | null; chapter_id: string | null; subject: string | null; chapter: string | null; task_type: "lesson" | "revision" | "practice" | "test" | "note" | "upload" | "repair"; title: string; status: "pending" | "completed" | "missed" | "skipped"; scheduled_for: string; duration_minutes: number; priority: number; href: string | null; mission_id: string | null; rescheduled_from_id: string | null; completed_at: string | null; /** Why DocDoe chose this task — from the adaptive planner, never invented. */ reason?: string | null; source?: string | null; repair_item_id?: string | null; revision_concept_key?: string | null; reason_codes?: string[]; reason_facts?: Record; target?: Record; }; export type LearningRevisionItem = { id: string; client_item_id: string; subject_id: string | null; chapter_id: string | null; subject: string | null; chapter: string | null; mission_id: string | null; topic_key: string | null; title: string; source_kind: string; source_ref: string | null; status: "pending" | "due" | "completed" | "dismissed"; due_at: string | null; completed_at: string | null; created_at: string; }; export type TodayPlan = { id: string; date: string; generation: number; version: string; status: string; available_minutes: number; planned_minutes: number; completed_minutes: number; tasks: LearningTask[]; generated_at: string; regenerated_at: string | null; }; export type MasteryState = | "not_started" | "introduced" | "developing" | "needs_repair" | "secure" | "revision_due" | "at_risk"; export type RepairItem = { id: string; subject_id: string | null; chapter_id: string | null; concept_key: string; concept_label: string; mission_id: string | null; error_category: string; diagnosis: string; recommended_activity: string; activity_prompt: string; priority: number; estimated_minutes: number; status: "open" | "resolved" | "escalated"; support_level: number; failed_attempts: number; retry_result: string | null; mastery_recovered: boolean; created_at: string; resolved_at: string | null; }; export type AcademicTopic = { topic_key: string; label: string; state: MasteryState; score: number; confidence: number; subject: string | null; chapter: string | null; next_review_at: string | null; }; export type AcademicTuitionSession = { class_session_id: string; subject: string | null; chapter: string | null; chapter_catalog_id: string | null; mission_id: string | null; topic: string | null; current_step_id: string; current_step_label: string; progress_percent: number; updated_at: string; href: string; }; export type AcademicCourse = { roadmap_id: string; topic: string; current_module: string | null; completed_topics: number; total_topics: number; progress_percent: number; updated_at: string; href: string; }; export type AcademicChatContext = { session_id: string; subject: string | null; chapter: string | null; topic: string | null; source_id: string | null; source_ref: string | null; source_label: string | null; activity_type: string | null; question_id: string | null; question_label: string | null; return_href: string | null; updated_at: string; href: string; }; export type NextAcademicAction = { type: | "COMPLETE_SETUP" | "CONTINUE_LESSON" | "CORRECT_MISTAKE" | "PRACTISE_TOPIC" | "REVISE_TOPIC" | "START_TODAYS_PLAN" | "CONTINUE_COURSE" | "REVIEW_PYQ" | "ASK_FOLLOWUP" | "START_NEXT_LESSON"; title: string; reason: string; action_label: string; subject: string | null; chapter: string | null; topic: string | null; href: string; resume_payload: Record; urgency: "low" | "normal" | "high" | "urgent"; estimated_minutes: number; }; export type LearningOnboardingResponse = { profile_id: string; plan_id: string; available_study_days: number; first_task_id: string; first_task_href: string; tasks: LearningTask[]; today_plan?: TodayPlan | null; }; export type LearningStateSummary = { profile: null | { id: string; class_level: string; board: string; exam_date: string | null; goal: string; daily_minutes: number; preferred_time: string | null; available_study_days: number; current_subject_id: string | null; current_chapter_id: string | null; current_mission_id: string | null; onboarding_completed: boolean; preferences?: Record; }; subjects: Array<{ id: string; name: string; board: string; class_level: string; priority: number; status: string; }>; chapters: Array<{ id: string; subject_id: string; catalog_id: string; title: string; order_index: number; importance: number; estimated_minutes: number; status: string; curated: boolean; }>; tasks: LearningTask[]; today_plan?: TodayPlan | null; lesson_progress: Array<{ id: string; chapter_id: string; chapter_catalog_id: string; chapter: string; subject_id: string; mission_id: string; status: "not_started" | "in_progress" | "completed"; progress_percent: number; current_step: number; completed_at: string | null; last_seen_at: string; }>; mastery: Array<{ id: string; subject_id: string | null; chapter_id: string | null; topic_key: string; topic_label: string; score: number; confidence: number; attempts_count: number; last_result: string | null; next_review_at: string | null; state: MasteryState; consecutive_success: number; error_categories: Record; last_evidence_at: string | null; }>; quiz_attempts: Array<{ id: string; quiz_id: string | null; daily_task_id: string | null; subject_id: string | null; chapter_id: string | null; title: string; subject: string | null; chapter: string | null; score: number; max_score: number; answers: Array>; corrections: Array>; missing_keywords: string[]; misconceptions: string[]; completed_at: string; }>; resources: Array<{ id: string; subject_id: string | null; chapter_id: string | null; subject: string | null; chapter: string | null; source_id: string | null; resource_type: string; title: string; status: string; storage_url: string | null; resource_data: Record; created_at: string; }>; repair_items: RepairItem[]; revision_items?: LearningRevisionItem[]; completed_lessons: number; completed_quiz_attempts: number; generated_resources: number; generated_notes: number; questions_asked: number; academic_state: { class_level: string | null; board: string | null; subjects: string[]; exam_date: string | null; days_to_exam: number | null; current_subject: string | null; current_chapter: string | null; current_topic: string | null; last_meaningful_activity: null | { kind: string; title: string; detail: string | null; occurred_at: string; href: string; }; unfinished_lesson: AcademicTuitionSession | null; recent_mistakes: Array<{ repair_id: string; topic_key: string; label: string; error_category: string; diagnosis: string; activity_prompt: string; subject: string | null; chapter: string | null; mission_id: string | null; occurred_at: string; }>; weak_topics: AcademicTopic[]; mastered_topics: AcademicTopic[]; revision_due: AcademicTopic[]; active_course: AcademicCourse | null; active_tuition_session: AcademicTuitionSession | null; recent_study_chat_context: AcademicChatContext | null; suggested_notifications: Array<{ id: string; title: string; body: string; kind: "info" | "success" | "warning" | "action"; href: string; created_at: string; }>; }; next_action: NextAcademicAction; }; export type StudentBrainSkillReadiness = { skill: | "concepts" | "numericals" | "derivations" | "pyqs" | "formulas" | "graphs" | "answer_writing" | "diagrams"; label: string; score: number; attempts: number; correct_attempts: number; evidence_level: "early" | "building" | "reliable"; last_attempted_at: string; }; export type StudentBrainMasteryItem = { topic_key: string; topic: string; subject: string | null; chapter: string | null; score: number; confidence: number; state: string; attempts: number; last_result: string | null; last_evidence_at: string | null; next_review_at: string | null; skill_readiness: StudentBrainSkillReadiness[]; }; export type StudentBrainContext = { schema_version: "student-brain-v1"; generated_at: string; focus: { subject: string | null; chapter: string | null; topic: string | null; available_minutes_today: number | null; }; profile: { class_level: string | null; board: string | null; subjects: string[]; preferred_language: string | null; learning_preferences: Record; }; exam: { name: string | null; date: string | null; days_remaining: number | null; syllabus: string | null; target_marks: number | null; total_marks: number | null; }; goal: { description: string | null; daily_minutes: number | null; available_minutes_today: number | null; }; weakest_topics: StudentBrainMasteryItem[]; retention_due: Array<{ topic_key: string; topic: string; subject: string | null; chapter: string | null; due_at: string; state: string; }>; recent_mistakes: Array<{ checkpoint_ref: string; topic_key: string; topic: string; subject: string | null; chapter: string | null; error_type: string; error_type_source: "server_classification" | "student_reflection"; internal_error_category: string; diagnosis: string | null; question_type: string | null; difficulty: string | null; time_spent_seconds: number | null; skill_tags: string[]; attempt_index: number; occurred_at: string; }>; recent_question_attempts: Array<{ checkpoint_ref: string; topic_key: string; topic: string; subject: string | null; chapter: string | null; kind: string; correct: boolean; hint_used: boolean; difficulty: string | null; time_spent_seconds: number | null; skill_tags: string[]; attempt_index: number; occurred_at: string; }>; recent_performance: Array<{ assessment_ref: string; subject: string | null; chapter: string | null; score: number; max_score: number; accuracy_percent: number; completed_at: string; }>; study_history: Array<{ date: string; planned_minutes: number; completed_minutes: number; completion_percent: number; subjects: string[]; }>; pyq_importance: Array<{ topic: string; subject: string | null; chapter: string | null; question_count: number; total_marks: number; years: number[]; priority: "high" | "medium" | "normal"; }>; resources: Array<{ kind: "source" | "generated" | "curated_chapter"; title: string; resource_type: string; subject: string | null; chapter: string | null; status: string; }>; next_action: null | { task_ref: string; title: string; task_type: string; subject: string | null; chapter: string | null; topic: string | null; chapter_catalog_id: string | null; mission_id: string | null; duration_minutes: number; reason: string | null; reason_codes: string[]; href: string | null; }; }; export function saveLearningOnboarding(payload: { class_level: string; board: string; subjects: string[]; /** Omit or null when the student does not know their exam date yet. */ exam_date: string | null; goal: string; daily_minutes: number; preferred_time: string | null; preferences: Record; }): Promise { return apiFetch("/learning-state/onboarding", { method: "POST", body: JSON.stringify(payload), }); } export function confirmLearningOnboarding(planId: string): Promise<{ profile_id: string; plan_id: string; confirmed_at: string; onboarding_completed: boolean; }> { return apiFetch("/learning-state/onboarding/confirm", { method: "POST", body: JSON.stringify({ plan_id: planId }), }); } export async function getLearningState(): Promise { const state = await apiFetch("/learning-state/me"); // A returning student may open Home before Tuition on a new study day. // Ensure is account-scoped and idempotent; an existing plan stays unchanged. if (state.profile?.onboarding_completed && !state.today_plan) { await ensureTodayPlan(); return apiFetch("/learning-state/me"); } return state; } export function getStudentBrainContext(): Promise { return apiFetch("/learning-state/brain-context"); } export function deleteLearningResource(resourceId: string): Promise { return apiDelete( `/learning-state/resources/${encodeURIComponent(resourceId)}`, ); } export function setLearningTaskStatus( taskId: string, status: "pending" | "completed" | "missed" | "skipped", reason?: string, ): Promise<{ task: LearningTask; recalculated_tasks: LearningTask[]; message: string; }> { return apiFetch(`/learning-state/tasks/${encodeURIComponent(taskId)}/status`, { method: "PATCH", body: JSON.stringify({ status, reason: reason ?? null }), }); } export type LessonProgressResult = { progress_id: string; status: "in_progress" | "completed"; progress_percent: number; completed_lessons: number; completed_task_id: string | null; message: string; }; export function saveLearningLessonProgress(payload: { chapter_catalog_id: string; mission_id: string; title: string; daily_task_id?: string | null; duration_minutes?: number; current_step?: number; progress_percent?: number; status?: "in_progress" | "completed"; }): Promise { return apiFetch("/learning-state/lessons/progress", { method: "POST", body: JSON.stringify(payload), }); } export type RevisionItemSaveResult = { item: LearningRevisionItem; replayed: boolean; message: string; }; export function saveLearningRevisionItem(payload: { client_item_id: string; title: string; chapter_catalog_id: string; mission_id?: string | null; topic_key?: string | null; source_kind: "manual_save" | "lesson_recap"; source_ref?: string | null; due_in_days?: number; }): Promise { return apiFetch("/learning-state/revision-items", { method: "POST", body: JSON.stringify(payload), }); } export type AssessmentConsequence = { attempt_id: string; mastery_before: number; mastery_after: number; revision_task: LearningTask | null; next_recommended_task_id: string | null; message: string; }; export type LearningAssessmentInput = { client_attempt_id?: string | null; title: string; topic_key: string; topic_label: string; score: number; max_score: number; subject_id?: string | null; chapter_id?: string | null; daily_task_id?: string | null; quiz_id?: string | null; mission_id?: string | null; answers?: Array>; corrections?: Array>; missing_keywords?: string[]; misconceptions?: string[]; mastery_already_recorded?: boolean; }; export function recordLearningAssessment( payload: LearningAssessmentInput, ): Promise { return apiFetch("/learning-state/assessments", { method: "POST", body: JSON.stringify(payload), }); } export function adjustLearningPlan(payload: { target_subject: string; replace_subject?: string | null; reason: string; chapters: string[]; }): Promise<{ tasks: LearningTask[]; unavailable_chapters: string[]; rescheduled_tasks: number; message: string; }> { return apiFetch("/learning-state/plan-adjustments", { method: "POST", body: JSON.stringify(payload), }); } export type CheckpointConsequence = { checkpoint_id: string; correct: boolean; replayed: boolean; error_category: string | null; diagnosis: string | null; recommended_activity: string | null; activity_prompt: string | null; repair_status: "created" | "escalated" | "resolved" | "none"; repair_item: RepairItem | null; mastery: { before_score: number; after_score: number; before_state: MasteryState; after_state: MasteryState; confidence: number; consecutive_success: number; next_review_at: string | null; }; message: string; }; export type CheckpointKind = | "recall_correct" | "checkpoint_mcq" | "checkpoint_short" | "checkpoint_numerical" | "checkpoint_diagram" | "board_answer" | "transfer_check" | "revision_recall"; export function recordLearningCheckpoint(payload: { client_event_id: string; concept_key: string; concept_label: string; chapter_catalog_id: string; mission_id: string; kind: CheckpointKind; question_id: string; question_type: "mcq" | "short" | "numerical" | "diagram" | "board"; prompt?: string; student_answer: string; correct_answer?: string; client_correct?: boolean; attempt_index?: number; hint_used?: boolean; expected_keywords?: string[]; time_spent_seconds?: number | null; difficulty?: "easy" | "medium" | "hard" | null; skill_tags?: string[]; error_reflection?: { error_type: "careless_error" | "misread_question" | "time_pressure"; note?: string | null; } | null; subject_id?: string | null; chapter_id?: string | null; daily_task_id?: string | null; }): Promise { return apiFetch("/learning-state/checkpoints", { method: "POST", body: JSON.stringify(payload), }); } export type PlanTodayResult = { plan_id: string; date: string; generation: number; version: string; status: string; daily_minutes: number; planned_minutes: number; tasks: LearningTask[]; created_task_ids: string[]; cancelled_task_ids: string[]; message: string; }; export function reconcileTodaysPlan(): Promise { return ensureTodayPlan(); } export function getTodayPlan(): Promise { return apiFetch("/learning-state/today-plan"); } export function ensureTodayPlan(): Promise { return apiFetch("/learning-state/today-plan/ensure", { method: "POST", body: JSON.stringify({}), }); } export function replanToday(payload: { idempotency_key: string; reason: | "explicit_replan" | "daily_minutes_changed" | "exam_date_changed" | "content_changed" | "meaningful_evidence"; }): Promise { return apiFetch("/learning-state/today-plan/replan", { method: "POST", body: JSON.stringify(payload), }); } export type RevisionRecallQuestion = { question_id: string; prompt: string; question_type: "mcq" | "short" | "numerical" | "diagram" | "board"; options: string[]; basis: "saved_mistake" | "linked_lesson"; reason: string; failure_count: number; }; export function getRevisionRecallQuestion(revisionItemId: string): Promise { return apiFetch(`/learning-state/revision-items/${encodeURIComponent(revisionItemId)}/question`); } export function recordRevisionResult( revisionItemId: string, payload: { client_event_id: string; response: string; question_id?: string }, ): Promise<{ item: LearningRevisionItem; evaluation: { evaluation_version: string; question_id: string; correct: boolean; awarded_marks: number; max_marks: number; mistake_categories: string[]; feedback: string; }; replayed: boolean; message: string; }> { return apiFetch( `/learning-state/revision-items/${encodeURIComponent(revisionItemId)}/result`, { method: "POST", body: JSON.stringify(payload) }, ); } export function listOpenStudyFollowUps(): Promise[]> { return apiFetch("/learning-state/study-followups"); } export function createStudyFollowUp(payload: { client_followup_id: string; chat_session_id: string; source_message_id?: string | null; kind: "practice" | "pyq_review" | "clarification" | "source_review"; title: string; subject?: string | null; chapter?: string | null; topic?: string | null; due_at?: string | null; estimated_minutes?: number; source_ref?: string | null; target?: Record; }): Promise> { return apiFetch("/learning-state/study-followups", { method: "POST", body: JSON.stringify(payload), }); }