from __future__ import annotations

from datetime import datetime
from typing import Any

from pydantic import BaseModel, Field


class ServicioCotizadoInput(BaseModel):
    catalogoId: str = Field(..., min_length=1, description="ID del servicio del catálogo")
    nombre: str = Field(..., min_length=1, description="Nombre del servicio")
    fase: int = Field(..., ge=0, le=3)
    tipoPago: str = Field(..., pattern="^(unico|mensual)$")
    precio: float = Field(..., ge=0, description="Precio (puede diferir del precioBase)")
    tiempoEntrega: str
    entregables: list[str] = Field(default_factory=list)


class PlanBucefaloInput(BaseModel):
    nivel: str = Field(..., description="Nivel: basico, estandar, premium, empresarial")
    precio: float = Field(..., ge=0)


class ClienteInput(BaseModel):
    nombre: str = Field(..., min_length=1)
    empresa: str = ""
    email: str = ""
    telefono: str = ""


class CotizacionCreate(BaseModel):
    numero: str = Field(..., min_length=1, description="Número de cotización (formato UJ{YY}{MM}{init}{seq})")
    fecha: datetime
    vigencia: datetime
    moneda: str = Field("MXN", pattern="^(MXN|USD)$")
    tipoCambio: str = "NA"
    proyecto: str = "MKT Digital"
    esquemaPago: str = Field("Pago Unico/Mensual", pattern="^(Pago Unico|Mensual|Pago Unico/Mensual)$")
    incluirBonos: bool = False
    incluirFinanciamiento: bool = False
    observaciones: str = ""
    asesorId: str = Field(..., min_length=1)
    cliente: ClienteInput
    servicios: list[ServicioCotizadoInput] = Field(..., min_length=1)
    planBucefalo: PlanBucefaloInput | None = None

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "numero": "UJ2605AG001",
                    "fecha": "2026-05-03",
                    "vigencia": "2026-05-24",
                    "moneda": "MXN",
                    "tipoCambio": "NA",
                    "proyecto": "MKT Digital",
                    "esquemaPago": "Pago Unico/Mensual",
                    "incluirBonos": False,
                    "incluirFinanciamiento": False,
                    "observaciones": "",
                    "asesorId": "cuid-asesor",
                    "cliente": {
                        "nombre": "Juan Pérez",
                        "empresa": "ACME Corp",
                        "email": "juan@acme.com",
                        "telefono": "4421234567",
                    },
                    "servicios": [
                        {
                            "catalogoId": "cuid-servicio",
                            "nombre": "SEO On-Page",
                            "fase": 3,
                            "tipoPago": "mensual",
                            "precio": 2900,
                            "tiempoEntrega": "7 - 14 dias",
                            "entregables": ["Keyword research"],
                        }
                    ],
                    "planBucefalo": {"nivel": "basico", "precio": 1000},
                }
            ]
        }
    }


class CotizacionUpdate(BaseModel):
    fecha: datetime | None = None
    vigencia: datetime | None = None
    moneda: str | None = Field(None, pattern="^(MXN|USD)$")
    tipoCambio: str | None = None
    proyecto: str | None = None
    esquemaPago: str | None = Field(None, pattern="^(Pago Unico|Mensual|Pago Unico/Mensual)$")
    incluirBonos: bool | None = None
    incluirFinanciamiento: bool | None = None
    observaciones: str | None = None
    estado: str | None = Field(None, pattern="^(borrador|enviada|aprobada|rechazada)$")
    cliente: ClienteInput | None = None
    servicios: list[ServicioCotizadoInput] | None = None
    planBucefalo: PlanBucefaloInput | None = None


class CambiarEstadoRequest(BaseModel):
    estado: str = Field(..., pattern="^(borrador|enviada|aprobada|rechazada)$")


class ActualizarPrecioRequest(BaseModel):
    servicioId: str = Field(..., min_length=1)
    precio: float = Field(..., ge=0)


class CotizacionResponse(BaseModel):
    id: str
    numero: str
    fecha: datetime
    vigencia: datetime
    moneda: str
    tipoCambio: str
    proyecto: str
    esquemaPago: str
    estado: str
    incluirBonos: bool
    incluirFinanciamiento: bool
    observaciones: str | None
    clienteId: str
    asesorId: str
    createdAt: datetime
    updatedAt: datetime
    cliente: dict[str, Any] | None = None
    asesor: dict[str, Any] | None = None
    servicios: list[dict[str, Any]] | None = None
    planBucefalo: dict[str, Any] | None = None

    model_config = {"from_attributes": True}
