"""Billing API routes — Spec 023."""

from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel, Field

from app import auth, billing_store
from app.permissions import can_manage_billing, can_read_billing, should_mask_sensitive

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


class PatchBillingBody(BaseModel):
    billing_state: str | None = None
    recurrence_active: bool | None = None
    external_customer_id: str | None = None
    plan_code: str | None = None
    activated_by: str | None = None


def _reader(user: auth.DeskUser = Depends(auth.get_current_user)) -> auth.DeskUser:
    if not can_read_billing(user.role):
        raise HTTPException(403, "permissão insuficiente")
    return user


def _manager(user: auth.DeskUser = Depends(auth.get_current_user)) -> auth.DeskUser:
    if not can_manage_billing(user.role):
        raise HTTPException(403, "permissão insuficiente")
    return user


@router.get("/summary")
def billing_summary(user: auth.DeskUser = Depends(_reader)):
    conn = auth.db()
    try:
        data = billing_store.summary(conn)
        if should_mask_sensitive(user.role):
            data["recent_validations"] = [
                billing_store._row_dict(r, mask=True)
                for r in conn.execute(
                    "SELECT * FROM billing_accounts ORDER BY updated_at DESC LIMIT 5"
                ).fetchall()
            ]
        return data
    finally:
        conn.close()


@router.get("/accounts")
def list_billing_accounts(
    billing_state: str = "",
    domain: str = "",
    limit: int = Query(100, ge=1, le=500),
    user: auth.DeskUser = Depends(_reader),
):
    conn = auth.db()
    try:
        mask = should_mask_sensitive(user.role)
        return billing_store.list_accounts(
            conn,
            billing_state=billing_state.strip() or None,
            domain=domain.strip() or None,
            limit=limit,
            mask=mask,
        )
    finally:
        conn.close()


@router.get("/accounts/by-domain/{domain}")
def billing_by_domain(domain: str, user: auth.DeskUser = Depends(_reader)):
    conn = auth.db()
    try:
        acc = billing_store.get_by_domain(conn, domain, mask=should_mask_sensitive(user.role))
    finally:
        conn.close()
    if not acc:
        raise HTTPException(404, "conta não encontrada")
    return acc


@router.get("/accounts/{account_id}")
def get_billing_account(account_id: int, user: auth.DeskUser = Depends(_reader)):
    conn = auth.db()
    try:
        acc = billing_store.get_account(conn, account_id, mask=should_mask_sensitive(user.role))
    finally:
        conn.close()
    if not acc:
        raise HTTPException(404, "conta não encontrada")
    return acc


@router.patch("/accounts/{account_id}")
def patch_billing_account(
    account_id: int,
    body: PatchBillingBody,
    user: auth.DeskUser = Depends(_manager),
):
    conn = auth.db()
    try:
        fields = body.model_dump(exclude_none=True)
        if body.recurrence_active and not fields.get("activated_by"):
            from datetime import datetime, timezone

            fields["activated_by"] = user.username
            fields["activated_at"] = datetime.now(timezone.utc).isoformat()
        acc = billing_store.patch_account(conn, account_id, **fields)
    finally:
        conn.close()
    if not acc:
        raise HTTPException(404, "conta não encontrada")
    return acc
