import random
from typing import Optional, List
from fastapi import HTTPException
from sqlmodel import Session
from app.models.models import Question
from app.crud import study_plan as crud_sp
from app.crud import quiz as crud_quiz
from app.services.quiz_service import shuffle_question_options


def get_study_plan(
    session: Session, user_id: int, topic_id: Optional[str] = None
) -> List[dict]:
    """Get study plan items with questions eagerly loaded."""
    items = crud_sp.get_items(session, user_id, topic_id)

    return [
        {
            "id": item.id,
            "question_id": item.question_id,
            "topic_id": item.topic_id,
            "sub_topic": item.sub_topic,
            "status": item.status,
            "source": item.source,
            "created_at": item.created_at,
            "question": item.question,
        }
        for item in items
    ]


def add_to_study_plan(
    session: Session, user_id: int, question_id: int
) -> dict:
    """Add a question to study plan (manual). Returns existing if duplicate."""
    question = session.get(Question, question_id)
    if not question:
        raise HTTPException(status_code=404, detail="Question not found")

    topic_id = crud_sp.resolve_topic_id(session, question_id)

    existing = crud_sp.find_existing(session, user_id, question_id)
    if existing:
        existing.question = question
        return existing

    item = crud_sp.add_item(session, user_id, question_id, topic_id, question.sub_topic, "manual")
    item.question = question
    return item


def bulk_add_to_study_plan(
    session: Session, user_id: int, question_ids: List[int], topic_id: str
) -> dict:
    """Batch add wrong-answer questions (auto). Skips duplicates."""
    added = 0
    for qid in question_ids:
        existing = crud_sp.find_existing(session, user_id, qid)
        if existing:
            continue
        question = session.get(Question, qid)
        if not question:
            continue
        crud_sp.add_item(session, user_id, qid, topic_id, question.sub_topic, "auto")
        added += 1
    return {"added": added}


def remove_from_study_plan(
    session: Session, user_id: int, item_id: int
) -> None:
    """Remove a study plan item. Raises 404 if not found or not owned."""
    item = crud_sp.get_item_by_id(session, item_id)
    if not item or item.user_id != user_id:
        raise HTTPException(status_code=404, detail="Study plan item not found")

    crud_sp.remove_item(session, item_id)


def start_study_quiz(
    session: Session, user_id: int, topic_id: Optional[str] = None
) -> dict:
    """Start a quiz using only the user's study plan questions."""
    items = crud_sp.get_items(session, user_id, topic_id)

    if not items:
        raise HTTPException(status_code=404, detail="No study plan items found")

    questions = [item.question for item in items if item.question]

    if not questions:
        raise HTTPException(status_code=404, detail="No valid questions in study plan")

    random.shuffle(questions)
    shuffled_questions = [shuffle_question_options(q) for q in questions]

    topic_name = "All Topics"
    if topic_id:
        topic = crud_quiz.get_topic_by_id(session, topic_id)
        if topic:
            topic_name = topic.name

    return {
        "quiz_id": f"study-plan-{topic_id or 'all'}",
        "quiz_name": f"Study Plan — {topic_name}",
        "mode": "study",
        "total_available": len(shuffled_questions),
        "questions": shuffled_questions,
    }

def update_item_status(
    session: Session, user_id: int, item_id: int, status: str
) -> dict:
    """Update the status of a specific study plan item."""
    if status not in ["not_started", "in_progress", "done"]:
        raise HTTPException(status_code=400, detail="Invalid status value")

    item = crud_sp.get_item_by_id(session, item_id)
    if not item or item.user_id != user_id:
        raise HTTPException(status_code=404, detail="Study plan item not found")

    updated_item = crud_sp.update_item_status(session, item_id, status)
    if not updated_item:
        raise HTTPException(status_code=404, detail="Failed to update item")

    return {
        "id": updated_item.id,
        "status": updated_item.status,
    }

