from uuid import UUID

from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.support.schemas.support_ticket import (
    SupportTicketCreate,
    SupportTicketListItemResponse,
    SupportTicketReplyCreate,
)
from src.apps.support.services.support_ticket_service import SupportTicketService
from src.core.constants import UserRole
from src.core.dependencies import require_min_role
from src.core.schemas.response import paginated, success
from src.database.session import get_db

router = APIRouter(prefix="/support", tags=["Support"])


def _serialize_ticket_summary(ticket) -> dict:
    """Matches the POST /support/tickets contract: {id, ticket_number,
    subject, status, created_at} — deliberately narrower than the list-item
    shape (no last_message_at)."""
    return {
        "id": ticket.id,
        "ticket_number": ticket.ticket_number,
        "subject": ticket.subject,
        "status": ticket.status,
        "created_at": ticket.created_at,
    }


def _serialize_message(message, author_name: str) -> dict:
    """Matches SupportTicketMessageResponse: {id, author_user_id,
    author_role_snapshot, author_name, body, created_at}. The author is
    always the caller replying to their own ticket, so author_name is
    derived from current_user rather than a fresh DB lookup."""
    return {
        "id": message.id,
        "author_user_id": message.author_user_id,
        "author_role_snapshot": message.author_role_snapshot,
        "author_name": author_name,
        "body": message.body,
        "created_at": message.created_at,
    }


@router.get("/tickets", response_model=dict)
async def list_tickets(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    """Paginated list of the current tenant's support tickets, newest first.
    All users in the tenant share one ticket list (not filtered per-submitter)."""
    service = SupportTicketService(db)
    tickets, total = await service.list(
        tenant_id=current_user.tenant_id,
        page=page,
        page_size=page_size,
    )
    return paginated(
        items=[SupportTicketListItemResponse.model_validate(t).model_dump() for t in tickets],
        total=total,
        page=page,
        page_size=page_size,
    )


@router.post("/tickets", response_model=dict, status_code=201)
async def create_ticket(
    body: SupportTicketCreate,
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    """Create a new support ticket (status=open) + its first message, in one
    transaction. Submitter identity is taken from the authenticated session."""
    service = SupportTicketService(db)
    ticket = await service.create(
        tenant_id=current_user.tenant_id,
        current_user=current_user,
        subject=body.subject,
        description=body.description,
    )
    return success(data=_serialize_ticket_summary(ticket), message="Support request submitted")


@router.get("/tickets/{ticket_id}", response_model=dict)
async def get_ticket(
    ticket_id: UUID,
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    """Ticket detail + full message thread, oldest first. 404 (never 403) if
    the ticket does not belong to the caller's tenant."""
    service = SupportTicketService(db)
    data = await service.get_by_id(tenant_id=current_user.tenant_id, ticket_id=ticket_id)
    return success(data=data)


@router.post("/tickets/{ticket_id}/messages", response_model=dict, status_code=201)
async def add_ticket_message(
    ticket_id: UUID,
    body: SupportTicketReplyCreate,
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    """Add a follow-up reply to the tenant's own ticket. Bumps
    last_message_at. 404 (never 403) if the ticket does not belong to the
    caller's tenant."""
    service = SupportTicketService(db)
    message = await service.add_message(
        tenant_id=current_user.tenant_id,
        ticket_id=ticket_id,
        current_user=current_user,
        body=body.body,
    )
    author_name = f"{current_user.first_name} {current_user.last_name}".strip()
    return success(data=_serialize_message(message, author_name), message="Reply added")
