"""Qualify router: decision qualification engine endpoint."""

from __future__ import annotations

from dataclasses import asdict

from fastapi import APIRouter, Depends
from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import get_db
from app.engine.qualifier import QualificationConfig, QualificationInput, qualify
from app.models.qualification import QualificationProtocol
from app.schemas.qualification import (
    QualificationProtocolCreate,
    QualificationProtocolOut,
    QualifyRequest,
    QualifyResponse,
)
from app.services.auth_service import get_current_identity
from app.services.qualify_ai_service import (
    AIFrameRequest,
    AIFrameResponse,
    AIMessage,
    AIQuestion,
    AIQualifyResult,
    ai_frame,
)

router = APIRouter()


# ── Pydantic wrappers for AI chat (FastAPI needs Pydantic, not dataclasses) ──


class AIMessagePayload(BaseModel):
    role: str
    content: str


class AIChatRequest(BaseModel):
    within_mandate: bool = False
    affected_count: int | None = None
    is_structural: bool = False
    context: str | None = None
    messages: list[AIMessagePayload] = []


class AIQuestionOut(BaseModel):
    id: str
    text: str
    options: list[str]


class AIQualifyResultOut(BaseModel):
    decision_type: str
    process: str
    recommended_modalities: list[str]
    recommend_onchain: bool
    onchain_reason: str | None
    confidence: str
    collective_available: bool
    record_in_observatory: bool
    reasons: list[str]


class AIChatResponse(BaseModel):
    done: bool
    questions: list[AIQuestionOut] = []
    result: AIQualifyResultOut | None = None
    explanation: str | None = None


async def _load_config(db: AsyncSession) -> QualificationConfig:
    """Load the active QualificationProtocol from DB, or fall back to defaults."""
    result = await db.execute(
        select(QualificationProtocol)
        .where(QualificationProtocol.is_active == True)  # noqa: E712
        .order_by(QualificationProtocol.created_at.desc())
        .limit(1)
    )
    proto = result.scalar_one_or_none()
    if proto is None:
        return QualificationConfig()
    return QualificationConfig(
        small_group_max=proto.small_group_max,
        collective_wot_min=proto.collective_wot_min,
        default_modalities=proto.default_modalities,
    )


@router.post("/", response_model=QualifyResponse)
async def qualify_decision(
    payload: QualifyRequest,
    db: AsyncSession = Depends(get_db),
) -> QualifyResponse:
    """Qualify a decision: determine type, process, and modalities.

    No authentication required — this is an advisory endpoint that helps
    users understand which decision pathway fits their situation.
    """
    config = await _load_config(db)
    inp = QualificationInput(
        within_mandate=payload.within_mandate,
        affected_count=payload.affected_count,
        is_structural=payload.is_structural,
        context_description=payload.context_description,
    )
    result = qualify(inp, config)
    return QualifyResponse(**asdict(result))


@router.post("/ai-chat", response_model=AIChatResponse)
async def ai_chat(payload: AIChatRequest) -> AIChatResponse:
    """Run one round of AI-assisted qualification framing.

    Round 1 (messages=[]) → returns 2 clarifying questions.
    Round 2 (messages set) → returns final qualification result.

    No auth required — advisory endpoint.
    """
    req = AIFrameRequest(
        within_mandate=payload.within_mandate,
        affected_count=payload.affected_count,
        is_structural=payload.is_structural,
        context=payload.context,
        messages=[AIMessage(role=m.role, content=m.content) for m in payload.messages],
    )
    resp = ai_frame(req)

    return AIChatResponse(
        done=resp.done,
        questions=[AIQuestionOut(id=q.id, text=q.text, options=q.options) for q in resp.questions],
        result=AIQualifyResultOut(**asdict(resp.result)) if resp.result else None,
        explanation=resp.explanation,
    )


@router.get("/protocol", response_model=QualificationProtocolOut | None)
async def get_active_protocol(
    db: AsyncSession = Depends(get_db),
) -> QualificationProtocolOut | None:
    """Return the currently active qualification protocol (thresholds)."""
    result = await db.execute(
        select(QualificationProtocol)
        .where(QualificationProtocol.is_active == True)  # noqa: E712
        .order_by(QualificationProtocol.created_at.desc())
        .limit(1)
    )
    proto = result.scalar_one_or_none()
    if proto is None:
        return None
    return QualificationProtocolOut.model_validate(proto)


@router.post("/protocol", response_model=QualificationProtocolOut, status_code=201)
async def create_protocol(
    payload: QualificationProtocolCreate,
    db: AsyncSession = Depends(get_db),
    _identity=Depends(get_current_identity),
) -> QualificationProtocolOut:
    """Create a new qualification protocol (requires auth).

    Deactivates the current active protocol before saving the new one.
    """
    # Deactivate current
    current = await db.execute(
        select(QualificationProtocol).where(QualificationProtocol.is_active == True)  # noqa: E712
    )
    for proto in current.scalars().all():
        proto.is_active = False

    import json
    proto = QualificationProtocol(
        name=payload.name,
        description=payload.description,
        small_group_max=payload.small_group_max,
        collective_wot_min=payload.collective_wot_min,
        default_modalities_json=json.dumps(payload.default_modalities),
        is_active=True,
    )
    db.add(proto)
    await db.commit()
    await db.refresh(proto)
    return QualificationProtocolOut.model_validate(proto)
