# ruff: noqa: F401,F403,F405,I001
from ._runtime import *  # noqa: F403,F405

from bot.services.support_service import TicketForbidden, TicketNotFound, TicketRateLimited
from db.dal import support_dal, user_dal
from db.models import SupportTicket, SupportTicketMessage


def _support_ticket_payload(ticket: SupportTicket) -> Dict[str, Any]:
    return {
        "ticket_id": ticket.ticket_id,
        "user_id": ticket.user_id,
        "subject": ticket.subject,
        "category": ticket.category,
        "priority": ticket.priority,
        "status": ticket.status,
        "assigned_admin_id": ticket.assigned_admin_id,
        "last_message_at": ticket.last_message_at.isoformat() if ticket.last_message_at else None,
        "last_message_role": ticket.last_message_role,
        "unread_user_count": int(ticket.unread_user_count or 0),
        "unread_admin_count": int(ticket.unread_admin_count or 0),
        "created_at": ticket.created_at.isoformat() if ticket.created_at else None,
        "updated_at": ticket.updated_at.isoformat() if ticket.updated_at else None,
        "closed_at": ticket.closed_at.isoformat() if ticket.closed_at else None,
    }


def _support_message_payload(message: SupportTicketMessage) -> Dict[str, Any]:
    return {
        "message_id": message.message_id,
        "ticket_id": message.ticket_id,
        "author_role": message.author_role,
        "author_user_id": message.author_user_id,
        "body": message.body,
        "is_internal_note": bool(message.is_internal_note),
        "created_at": message.created_at.isoformat() if message.created_at else None,
        "read_by_user_at": message.read_by_user_at.isoformat() if message.read_by_user_at else None,
        "read_by_admin_at": message.read_by_admin_at.isoformat()
        if message.read_by_admin_at
        else None,
    }


def _support_limit_offset(request: web.Request) -> tuple[int, int]:
    limit = max(1, min(100, int(request.query.get("limit", 25) or 25)))
    offset = max(0, int(request.query.get("offset", 0) or 0))
    return limit, offset


async def support_tickets_route(request: web.Request) -> web.Response:
    user_id = _require_user_id(request)
    limit, offset = _support_limit_offset(request)
    status_filter = request.query.get("status") or None
    async_session_factory: sessionmaker = request.app["async_session_factory"]
    async with async_session_factory() as session:
        tickets = await support_dal.list_user_tickets(
            session,
            user_id,
            limit=limit,
            offset=offset,
            status_filter=status_filter,
        )
        counts = await support_dal.user_ticket_counts(session, user_id)
    return web.json_response(
        {
            "ok": True,
            "tickets": [_support_ticket_payload(t) for t in tickets],
            "counts": counts,
        }
    )


async def support_create_ticket_route(request: web.Request) -> web.Response:
    user_id = _require_user_id(request)
    payload, error = _validate_model_payload(CreateTicketPayload, await _read_json(request))
    if error:
        return error
    service = request.app["support_service"]
    try:
        ticket = await service.create_ticket(
            user_id,
            payload.subject,
            payload.category,
            payload.priority,
            payload.body,
        )
    except TicketForbidden:
        return _json_error(403, "ticket_forbidden", "Support ticket action is forbidden")
    except TicketRateLimited:
        return _json_error(429, "ticket_rate_limited", "Too many support tickets")
    return web.json_response({"ok": True, "ticket": _support_ticket_payload(ticket)})


async def support_ticket_detail_route(request: web.Request) -> web.Response:
    user_id = _require_user_id(request)
    ticket_id = int(request.match_info["id"])
    async_session_factory: sessionmaker = request.app["async_session_factory"]
    async with async_session_factory() as session:
        ticket, messages = await support_dal.get_ticket(session, ticket_id, include_internal=False)
        if not ticket or ticket.user_id != user_id:
            return _json_error(404, "not_found", "Ticket not found")
    return web.json_response(
        {
            "ok": True,
            "ticket": _support_ticket_payload(ticket),
            "messages": [_support_message_payload(m) for m in messages],
        }
    )


async def support_ticket_reply_route(request: web.Request) -> web.Response:
    user_id = _require_user_id(request)
    ticket_id = int(request.match_info["id"])
    payload, error = _validate_model_payload(TicketReplyPayload, await _read_json(request))
    if error:
        return error
    service = request.app["support_service"]
    try:
        ticket, message = await service.reply_as_user(user_id, ticket_id, payload.body)
    except TicketForbidden:
        return _json_error(403, "ticket_forbidden", "Support ticket action is forbidden")
    except TicketNotFound:
        return _json_error(404, "not_found", "Ticket not found")
    return web.json_response(
        {
            "ok": True,
            "ticket": _support_ticket_payload(ticket),
            "message": _support_message_payload(message),
        }
    )


async def support_ticket_read_route(request: web.Request) -> web.Response:
    user_id = _require_user_id(request)
    ticket_id = int(request.match_info["id"])
    service = request.app["support_service"]
    try:
        await service.mark_read_as_user(user_id, ticket_id)
    except TicketNotFound:
        return _json_error(404, "not_found", "Ticket not found")
    return web.json_response({"ok": True})


async def support_unread_route(request: web.Request) -> web.Response:
    user_id = _require_user_id(request)
    async_session_factory: sessionmaker = request.app["async_session_factory"]
    async with async_session_factory() as session:
        user = await user_dal.get_user_by_id(session, user_id)
        if user and user.is_banned:
            return _json_error(403, "ticket_forbidden", "Support ticket action is forbidden")
        unread = await support_dal.count_user_unread(session, user_id)
    return web.json_response({"ok": True, "unread": unread})
