"""Pydantic schemas para request/response de la API."""
from pydantic import BaseModel
from typing import Optional
from datetime import datetime


class PackageOut(BaseModel):
    id: str
    name: str
    minutes: int
    price: float
    color: str

    class Config:
        from_attributes = True


class SellRequest(BaseModel):
    package_id: str
    payment_method: str = "cash"
    amount_received: float = 0.0
    cashier: str = "default"
    agent_id: Optional[str] = None  # cual programador usar (None = primero disponible)
    timeout: int = 30
    red_minutes: Optional[int] = None    # solo para combos custom (C-...)
    green_minutes: Optional[int] = None
    blue_minutes: Optional[int] = None


class RetryRequest(BaseModel):
    timeout: int = 30


class SellResponse(BaseModel):
    session_id: str
    status: str
    package_name: str
    minutes: int
    amount: float
    folio_number: Optional[str] = None
    programmed_at: Optional[str] = None
    message: Optional[str] = None


class SessionOut(BaseModel):
    id: str
    package_id: str
    package_name: Optional[str] = None
    status: str
    red_minutes: int
    green_minutes: int
    blue_minutes: int
    payment_method: str
    amount: float
    cashier: str
    folio_number: Optional[str] = None
    programmed_at: Optional[datetime] = None
    expires_at: Optional[datetime] = None
    created_at: Optional[datetime] = None

    class Config:
        from_attributes = True


class HardwareStatus(BaseModel):
    agent_reachable: bool
    programmer_connected: bool


class AgentRegister(BaseModel):
    id: str
    name: str
    host: str
    port: int = 5555


class AgentOut(BaseModel):
    """Respuesta publica de agent (sin token)."""
    id: str
    name: str
    host: str
    port: int
    status: str
    last_heartbeat: Optional[datetime] = None

    class Config:
        from_attributes = True


class AgentWithToken(AgentOut):
    """Respuesta con token (solo al registrar/regenerar)."""
    token: Optional[str] = None


class OfflineSale(BaseModel):
    """Una venta realizada offline en la estacion."""
    session_id: str
    package_id: str
    red_minutes: int
    green_minutes: int
    blue_minutes: int
    payment_method: str = "cash"
    amount: float
    cashier: str = "default"
    agent_id: Optional[str] = None
    programmed_at: Optional[str] = None
    created_at: Optional[str] = None


class SyncUploadRequest(BaseModel):
    """Lote de ventas offline para sincronizar."""
    agent_id: str
    sales: list[OfflineSale]


class SyncUploadResponse(BaseModel):
    status: str = "ok"
    accepted: int       # nuevas insertadas


class CortesiaRequest(BaseModel):
    package_id: str
    pin_supervisor: str = ""
    cashier: str = "default"
    motivo: str = ""
    supervisor: str = ""
    agent_id: Optional[str] = None
    timeout: int = 30
    red_minutes: Optional[int] = None
    green_minutes: Optional[int] = None
    blue_minutes: Optional[int] = None


class ReprogramRequest(BaseModel):
    package_id: str
    pin_supervisor: str = ""
    cashier: str = "default"
    motivo: str = ""
    supervisor: str = ""
    agent_id: Optional[str] = None
    timeout: int = 30


class AnulacionRequest(BaseModel):
    pin_supervisor: str = ""
    cashier: str = "default"
    motivo: str = ""
    supervisor: str = ""


class ValidarPinRequest(BaseModel):
    pin: str
    accion: str
    solicitante: str = ""
    motivo: str


class ValidarPinResponse(BaseModel):
    status: str
    supervisor: Optional[str] = None
    supervisor_id: Optional[int] = None
    permiso: Optional[str] = None
    message: Optional[str] = None


class SupervisorActionResponse(BaseModel):
    status: str
    session_id: Optional[str] = None
    folio_number: Optional[str] = None
    package_name: Optional[str] = None
    minutes: Optional[int] = None
    supervisor: Optional[str] = None
    message: Optional[str] = None


class PackageReport(BaseModel):
    package_name: str
    count: int
    revenue: float


class AnulacionReport(BaseModel):
    folio: str
    package: str
    amount: float
    supervisor: str
    motivo: str
    cashier: str


class AutorizacionReport(BaseModel):
    action_label: str       # "Cortesia" | "Reprogramacion"
    folio: str
    supervisor: str
    motivo: str
    cashier: str
    detail: str             # "Paquete 60 min" o "Paq A -> Paq B"


class DailyReport(BaseModel):
    date: str
    total_sales: int
    total_revenue: float
    by_package: list[PackageReport]
    anulaciones: list[AnulacionReport] = []
    autorizaciones: list[AutorizacionReport] = []


# --- Combos custom y terminales ---

class ComboRegisterRequest(BaseModel):
    combo_id: str                        # "C-A1B2C3"
    config: Optional[dict] = None        # config visual completa (colores, minutos, estilo)

class ComboRegistryOut(BaseModel):
    combo_id: str
    agent_id: str
    config_json: Optional[str] = None
    created_at: Optional[datetime] = None

    class Config:
        from_attributes = True

class TerminalPackageCreate(BaseModel):
    combo_id: str
    name: str
    price: float

class TerminalPackageOut(BaseModel):
    id: int
    agent_id: str
    combo_id: str
    name: str
    price: float
    active: bool

    class Config:
        from_attributes = True
