"""Manager sign-off and certificate router."""
import secrets
from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import and_, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import require_roles
from app.core.rbac import Role
from app.db.base import get_db
from app.models import (
    Certificate,
    LearnerProgress,
    ManagerSignoff,
    ModuleRule,
    SignoffStatus,
    UserModel,
)
from app.schemas import CertificateOut, SignoffCreate, SignoffOut
from app.services.audit import log_audit

router = APIRouter(prefix="/api/v1", tags=["signoff"])


@router.post("/readiness/{learner_id}/signoff", response_model=SignoffOut, status_code=201)
async def create_signoff(
    learner_id: UUID,
    body: SignoffCreate,
    db: AsyncSession = Depends(get_db),
    current_user: UserModel = Depends(
        require_roles(Role.SALES_MANAGER, Role.DEPT_HEAD, Role.LD_ADMIN)
    ),
) -> SignoffOut:
    """Manager signs off on a learner's readiness for a module."""
    # Check existing signoff
    existing = await db.execute(
        select(ManagerSignoff).where(
            and_(
                ManagerSignoff.learner_id == learner_id,
                ManagerSignoff.module_id == body.module_id,
            )
        )
    )
    signoff = existing.scalar_one_or_none()
    if signoff:
        # Update existing
        signoff.status = SignoffStatus(body.status)
        signoff.comments = body.comments
        signoff.manager_id = current_user.id
    else:
        signoff = ManagerSignoff(
            learner_id=learner_id,
            module_id=body.module_id,
            manager_id=current_user.id,
            status=SignoffStatus(body.status),
            comments=body.comments,
        )
        db.add(signoff)

    await log_audit(db, current_user.id, "signoff_created", "signoff", signoff.id,
                    details={"learner_id": str(learner_id), "status": body.status})

    # If approved, update learner progress and issue certificate
    if body.status == SignoffStatus.APPROVED.value:
        progress_result = await db.execute(
            select(LearnerProgress).where(
                and_(
                    LearnerProgress.learner_id == learner_id,
                    LearnerProgress.module_id == body.module_id,
                )
            )
        )
        progress = progress_result.scalar_one_or_none()
        if progress:
            progress.signed_off = True

            # Check if module is mandatory and passed
            rules_result = await db.execute(
                select(ModuleRule).where(ModuleRule.module_id == body.module_id)
            )
            rules = rules_result.scalar_one_or_none()
            if rules and rules.is_mandatory and progress.is_passed:
                # Issue certificate
                cert_result = await db.execute(
                    select(Certificate).where(
                        and_(
                            Certificate.learner_id == learner_id,
                            Certificate.module_id == body.module_id,
                        )
                    )
                )
                if not cert_result.scalar_one_or_none():
                    cert = Certificate(
                        learner_id=learner_id,
                        module_id=body.module_id,
                        certificate_number=f"SQ-{secrets.token_hex(8).upper()}",
                    )
                    db.add(cert)
                    await log_audit(db, current_user.id, "certificate_issued", "certificate",
                                    cert.id, details={"learner_id": str(learner_id)})

    await db.commit()
    await db.refresh(signoff)
    return SignoffOut.model_validate(signoff)


@router.get("/signoffs", response_model=list[SignoffOut])
async def list_signoffs(
    status: str | None = None,
    db: AsyncSession = Depends(get_db),
    current_user: UserModel = Depends(
        require_roles(Role.SALES_MANAGER, Role.DEPT_HEAD, Role.LD_ADMIN)
    ),
) -> list[SignoffOut]:
    """List sign-offs, optionally filtered by status."""
    query = select(ManagerSignoff)
    if status:
        query = query.where(ManagerSignoff.status == SignoffStatus(status))
    query = query.order_by(ManagerSignoff.created_at.desc())
    result = await db.execute(query)
    signoffs = result.scalars().all()
    return [SignoffOut.model_validate(s) for s in signoffs]


@router.get("/certificates/{learner_id}", response_model=list[CertificateOut])
async def get_certificates(
    learner_id: UUID,
    db: AsyncSession = Depends(get_db),
    current_user: UserModel = Depends(require_roles(
        Role.LEARNER, Role.SALES_MANAGER, Role.DEPT_HEAD, Role.LD_ADMIN
    )),
) -> list[CertificateOut]:
    """Get certificates for a learner."""
    # Learners can only see their own certificates
    if any(r.name == Role.LEARNER.value for r in current_user.roles):
        if current_user.id != learner_id:
            raise HTTPException(status_code=403, detail="Can only view your own certificates")

    result = await db.execute(
        select(Certificate).where(Certificate.learner_id == learner_id)
    )
    certs = result.scalars().all()
    return [CertificateOut.model_validate(c) for c in certs]
