"""Question category management — organise bank questions by topic/subject."""
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.orm import Session

from app.database import get_db
from app.models.question import Question
from app.models.question_category import QuestionCategory
from app.models.quiz import Quiz
from app.models.user import User
from app.utils.auth import get_current_user, require_moderator

router = APIRouter()


class QCatCreate(BaseModel):
    name: str
    description: str | None = None


class QCatResponse(BaseModel):
    id: int
    name: str
    description: str | None
    question_count: int = 0

    model_config = {"from_attributes": True}


@router.get("/", response_model=list[QCatResponse])
def list_question_categories(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    cats = db.query(QuestionCategory).order_by(QuestionCategory.name).all()
    return [
        QCatResponse(
            id=c.id, name=c.name, description=c.description,
            question_count=db.query(Question).filter(Question.question_category_id == c.id).count(),
        )
        for c in cats
    ]


@router.post("/", response_model=QCatResponse)
def create_question_category(
    data: QCatCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_moderator),
):
    if not data.name.strip():
        raise HTTPException(status_code=400, detail="Name cannot be empty")
    existing = db.query(QuestionCategory).filter(QuestionCategory.name == data.name.strip()).first()
    if existing:
        raise HTTPException(status_code=400, detail="Category already exists")
    cat = QuestionCategory(name=data.name.strip(), description=data.description, user_id=current_user.id)
    db.add(cat)
    db.commit()
    db.refresh(cat)
    return QCatResponse(id=cat.id, name=cat.name, description=cat.description, question_count=0)


@router.patch("/{cat_id}", response_model=QCatResponse)
def update_question_category(
    cat_id: int,
    data: QCatCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_moderator),
):
    cat = db.query(QuestionCategory).filter(QuestionCategory.id == cat_id).first()
    if not cat:
        raise HTTPException(status_code=404, detail="Category not found")
    cat.name = data.name.strip()
    cat.description = data.description
    db.commit()
    count = db.query(Question).filter(Question.question_category_id == cat_id).count()
    return QCatResponse(id=cat.id, name=cat.name, description=cat.description, question_count=count)


@router.delete("/{cat_id}", status_code=204)
def delete_question_category(
    cat_id: int,
    move_to: int | None = None,  # optional: move questions to this category instead of uncategorizing
    db: Session = Depends(get_db),
    current_user: User = Depends(require_moderator),
):
    cat = db.query(QuestionCategory).filter(QuestionCategory.id == cat_id).first()
    if not cat:
        raise HTTPException(status_code=404, detail="Category not found")
    if move_to is not None:
        target = db.query(QuestionCategory).filter(QuestionCategory.id == move_to).first()
        if not target:
            raise HTTPException(status_code=404, detail="Target category not found")
        db.query(Question).filter(Question.question_category_id == cat_id).update(
            {"question_category_id": move_to}
        )
    else:
        db.query(Question).filter(Question.question_category_id == cat_id).update(
            {"question_category_id": None}
        )
    db.delete(cat)
    db.commit()


@router.post("/{cat_id}/create-quiz")
def create_quiz_from_question_category(
    cat_id: int,
    title: str,
    mode: str = "timed",
    time_limit_minutes: int | None = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_moderator),
):
    """Create a new quiz from all questions in a question category."""
    cat = db.query(QuestionCategory).filter(QuestionCategory.id == cat_id).first()
    if not cat:
        raise HTTPException(status_code=404, detail="Category not found")
    if not title.strip():
        raise HTTPException(status_code=400, detail="Title is required")
    if mode not in ("timed", "learning"):
        raise HTTPException(status_code=400, detail="Mode must be timed or learning")

    source_questions = db.query(Question).filter(
        Question.question_category_id == cat_id
    ).order_by(Question.id).all()

    if not source_questions:
        raise HTTPException(status_code=400, detail="This category has no questions")

    first_quiz = db.query(Quiz).filter(Quiz.id == source_questions[0].source_quiz_id).first() if source_questions[0].source_quiz_id else None
    if not first_quiz:
        raise HTTPException(status_code=400, detail="Cannot determine source section — questions must have an origin quiz")

    from app.models.quiz_question_link import QuizQuestionLink
    new_quiz = Quiz(
        section_id=first_quiz.section_id,
        user_id=current_user.id,
        title=title.strip(),
        questions_count=len(source_questions),
        mode=mode,
        time_limit_minutes=time_limit_minutes,
    )
    db.add(new_quiz)
    db.flush()

    # Reference existing questions via junction — no copies, edits propagate
    for pos, sq in enumerate(source_questions):
        db.add(QuizQuestionLink(quiz_id=new_quiz.id, question_id=sq.id, position=pos))

    db.commit()
    db.refresh(new_quiz)
    return {"id": new_quiz.id, "title": new_quiz.title, "questions_count": new_quiz.questions_count}
