"""AI question generation — live LLM or local generator."""

from __future__ import annotations

from app.prompts import render_role_question_prompts
from app.schemas.common import JobStatus
from app.schemas.questions import (
    Difficulty,
    GeneratedOption,
    GeneratedQuestion,
    QuestionGenRequest,
    QuestionGenResponse,
    QuestionType,
    RoleQuestionGenRequest,
    RoleQuestionGenResponse,
)
from app.services.ai_generate import generate_json


def _local_questions(
    *,
    count: int,
    qtype: QuestionType,
    difficulty: Difficulty,
    topic: str,
) -> list[dict]:
    items = []
    for i in range(count):
        stem = f"[{difficulty.value}] Explain a key concept about {topic} (Q{i + 1})."
        options: list[dict] = []
        answer = f"Sample answer covering {topic}."
        if qtype == QuestionType.MCQ:
            options = [
                {"key": "A", "text": f"Correct point about {topic}", "is_correct": True},
                {"key": "B", "text": "Plausible distractor", "is_correct": False},
                {"key": "C", "text": "Unrelated option", "is_correct": False},
                {"key": "D", "text": "Common misconception", "is_correct": False},
            ]
            answer = "A"
            stem = f"Which statement best describes {topic}? (Q{i + 1})"
        elif qtype == QuestionType.TRUE_FALSE:
            options = [
                {"key": "T", "text": "True", "is_correct": True},
                {"key": "F", "text": "False", "is_correct": False},
            ]
            answer = "T"
            stem = f"{topic} is an important topic for this role. True or False? (Q{i + 1})"
        elif qtype == QuestionType.CODING:
            stem = f"Write a short solution related to {topic} (Q{i + 1})."
            answer = "# sample solution\npass"
        items.append(
            {
                "id": f"q-{i + 1}",
                "question_type": qtype.value,
                "difficulty": difficulty.value,
                "stem": stem,
                "options": options,
                "answer": answer,
                "explanation": f"Generated locally for {topic}.",
                "metadata": {},
            }
        )
    return items


def _parse_questions(raw: list, fallback_type: QuestionType, fallback_diff: Difficulty) -> list[GeneratedQuestion]:
    out: list[GeneratedQuestion] = []
    for i, item in enumerate(raw or []):
        if not isinstance(item, dict):
            continue
        qtype = item.get("question_type", fallback_type.value)
        diff = item.get("difficulty", fallback_diff.value)
        try:
            qt = QuestionType(qtype)
        except ValueError:
            qt = fallback_type
        try:
            df = Difficulty(diff)
        except ValueError:
            df = fallback_diff
        options = [
            GeneratedOption(
                key=str(o.get("key", chr(65 + j))),
                text=str(o.get("text", "")),
                is_correct=bool(o.get("is_correct", False)),
            )
            for j, o in enumerate(item.get("options") or [])
            if isinstance(o, dict)
        ]
        out.append(
            GeneratedQuestion(
                id=str(item.get("id", f"q-{i + 1}")),
                question_type=qt,
                difficulty=df,
                stem=str(item.get("stem") or item.get("text") or f"Question {i + 1}"),
                options=options,
                answer=item.get("answer"),
                explanation=item.get("explanation"),
                metadata=item.get("metadata") or {},
            )
        )
    return out


class QuestionsService:
    async def generate(self, payload: QuestionGenRequest) -> QuestionGenResponse:
        system = (
            "You are an assessment question generator. "
            "Return JSON: {\"questions\":[{\"id\",\"question_type\",\"difficulty\","
            "\"stem\",\"options\":[{\"key\",\"text\",\"is_correct\"}],\"answer\",\"explanation\"}]}"
        )
        user = (
            f"Subject: {payload.subject}\nTopic: {payload.topic}\n"
            f"Type: {payload.question_type.value}\nDifficulty: {payload.difficulty.value}\n"
            f"Count: {payload.count}\nLanguage: {payload.language}\n"
            f"Context: {payload.context or 'none'}\nConstraints: {payload.constraints}"
        )

        def local() -> dict:
            return {
                "questions": _local_questions(
                    count=payload.count,
                    qtype=payload.question_type,
                    difficulty=payload.difficulty,
                    topic=f"{payload.subject} / {payload.topic}",
                )
            }

        data, stub, provider = await generate_json(
            system=system, user=user, local_factory=local
        )
        questions = _parse_questions(
            data.get("questions", []), payload.question_type, payload.difficulty
        )
        if not questions:
            questions = _parse_questions(
                local()["questions"], payload.question_type, payload.difficulty
            )
            stub, provider = True, "local"

        return QuestionGenResponse(
            correlation_id=payload.correlation_id,
            status=JobStatus.SUCCEEDED,
            stub=stub,
            message=f"Generated {len(questions)} question(s) via {provider}",
            questions=questions,
        )

    async def generate_from_role(
        self, payload: RoleQuestionGenRequest
    ) -> RoleQuestionGenResponse:
        system, user_prompt = render_role_question_prompts(
            persona=payload.persona,
            role_title=payload.role_title,
            seniority=payload.seniority or "",
            department=payload.department or "",
            job_description=payload.job_description,
            skills=payload.skills,
            question_types=[qt.value for qt in payload.question_types],
            difficulty=payload.difficulty.value,
            count=payload.count,
            language=payload.language,
            instructions=payload.instructions or "",
        )
        system = (
            system
            + "\nReturn JSON only: {\"questions\":[{\"id\",\"question_type\",\"difficulty\","
            "\"stem\",\"options\":[{\"key\",\"text\",\"is_correct\"}],\"answer\",\"explanation\"}]}"
        )
        primary_type = payload.question_types[0] if payload.question_types else QuestionType.SHORT_ANSWER

        def local() -> dict:
            topic = payload.role_title
            if payload.skills:
                topic = f"{payload.role_title} ({', '.join(payload.skills[:3])})"
            return {
                "questions": _local_questions(
                    count=payload.count,
                    qtype=primary_type,
                    difficulty=payload.difficulty,
                    topic=topic,
                )
            }

        data, stub, provider = await generate_json(
            system=system, user=user_prompt, local_factory=local
        )
        questions = _parse_questions(
            data.get("questions", []), primary_type, payload.difficulty
        )
        if not questions:
            questions = _parse_questions(
                local()["questions"], primary_type, payload.difficulty
            )
            stub, provider = True, "local"

        return RoleQuestionGenResponse(
            correlation_id=payload.correlation_id,
            role_title=payload.role_title,
            persona=payload.persona,
            status=JobStatus.SUCCEEDED,
            stub=stub,
            message=f"Generated {len(questions)} role question(s) via {provider}",
            prompt_preview={"system": system, "user": user_prompt},
            questions=questions,
        )
