from decimal import Decimal

from sqlalchemy import JSON, Integer, Numeric, String, Text, text
from sqlalchemy.orm import Mapped, mapped_column

from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base


class Supplier(Base, TenantScopedMixin, TimestampMixin):
    """Catálogo de Proveedores (navieras, aerolíneas, transportistas, agentes, etc.).

    Los campos multi-valor (clasificaciones, cobertura por país/puerto/aduana) se
    guardan como listas JSON. Direcciones, contactos y documentos viven en tablas
    relacionadas (crm.addresses, crm.contacts, crm.documents).
    """

    __tablename__ = "suppliers"
    __table_args__ = {"schema": "crm"}

    id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)

    # ----- Datos generales -----
    name: Mapped[str] = mapped_column(String(255), nullable=False)  # razón social
    trade_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
    rfc: Mapped[str | None] = mapped_column(String(13), nullable=True, index=True)
    curp: Mapped[str | None] = mapped_column(String(18), nullable=True)
    person_type: Mapped[str | None] = mapped_column(String(10), nullable=True)  # fisica | moral
    status: Mapped[str] = mapped_column(String(20), nullable=False, server_default=text("'active'"))
    # Clasificación (múltiple): naviera, aerolinea, transportista_terrestre, ferrocarril,
    # agente_aduanal, agente_carga, agente_corresponsal, almacen, aseguradora, paqueteria, otro
    classifications: Mapped[list | None] = mapped_column(JSON, nullable=True, default=list)
    # Texto libre cuando la clasificación incluye "otro"
    classification_other: Mapped[str | None] = mapped_column(String(120), nullable=True)

    # ----- Información comercial -----
    services_offered: Mapped[str | None] = mapped_column(Text, nullable=True)
    coverage: Mapped[str | None] = mapped_column(String(20), nullable=True)  # nacional | internacional | ambos
    countries: Mapped[list | None] = mapped_column(JSON, nullable=True, default=list)
    ports: Mapped[list | None] = mapped_column(JSON, nullable=True, default=list)
    airports: Mapped[list | None] = mapped_column(JSON, nullable=True, default=list)
    customs: Mapped[list | None] = mapped_column(JSON, nullable=True, default=list)  # aduanas
    business_hours: Mapped[str | None] = mapped_column(String(255), nullable=True)
    quote_currency: Mapped[str | None] = mapped_column(String(3), nullable=True)
    avg_response_time: Mapped[str | None] = mapped_column(String(120), nullable=True)
    commercial_notes: Mapped[str | None] = mapped_column(Text, nullable=True)
    email: Mapped[str | None] = mapped_column(String(255), nullable=True)
    phone: Mapped[str | None] = mapped_column(String(40), nullable=True)
    website: Mapped[str | None] = mapped_column(String(255), nullable=True)

    # ----- Información fiscal -----
    tax_regime: Mapped[str | None] = mapped_column(String(120), nullable=True)
    payment_method: Mapped[str | None] = mapped_column(String(60), nullable=True)
    payment_form: Mapped[str | None] = mapped_column(String(60), nullable=True)
    credit_limit: Mapped[Decimal | None] = mapped_column(Numeric(14, 2), nullable=True)
    credit_days: Mapped[int | None] = mapped_column(Integer, nullable=True)
    commercial_terms: Mapped[str | None] = mapped_column(Text, nullable=True)

    # ----- Observaciones y auditoría -----
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)  # comentarios generales
    internal_notes: Mapped[str | None] = mapped_column(Text, nullable=True)
    owner_user_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
    created_by: Mapped[str | None] = mapped_column(String(64), nullable=True)
    updated_by: Mapped[str | None] = mapped_column(String(64), nullable=True)
