"""
Modelo ORM para datos específicos de Inventario y Manufactura (S-Partes) - Anexo 24
"""

from typing import TYPE_CHECKING, Optional, List
from decimal import Decimal
from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
    Integer,
    Numeric,
    PrimaryKeyConstraint,
    String,
    Boolean,
    ForeignKeyConstraint
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship

if TYPE_CHECKING:
    from api.v1.modules.a76.parts.models import Part

# Importar los modelos Aphis para asegurar su registro en SQLAlchemy
import api.v1.modules.a24.inv.inv_aphis.models as aphis_models
class InvPart(Base, TenantScopedMixin, TimestampMixin):
    """
    Tabla inv_partes: Extensión de Anexo 24 para Inventarios (SPartes).
    """

    __tablename__ = "inv_partes"
    __table_args__ = (
        PrimaryKeyConstraint("id", name="inv_partes_pkey"),
        ForeignKeyConstraint(
            ["id"], ["a76.parts.id"], name="fk_inv_partes_master"
        ),
        {"schema": "a24", "extend_existing": True},
    )

    # Relación 1:1 - El ID es el mismo de la tabla maestra
    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=False)

    # --- 1. ATRIBUTOS PRINCIPALES DE INVENTARIO ---
    part_type: Mapped[Optional[str]] = mapped_column(String(10)) # TIPOPARTE
    material_type: Mapped[Optional[str]] = mapped_column(String(10)) # TIPOMAT
    
    reference_number: Mapped[Optional[str]] = mapped_column(String(70)) # NUMPARTEREF
    flex_reference_number: Mapped[Optional[str]] = mapped_column(String(120)) # NUMPARTEREFFLEX

    # Conversiones
    equivalent_uom: Mapped[Optional[str]] = mapped_column(String(5)) # UNIMEDEQUIV
    conversion_factor: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 8)) # FACTORCONV
    
    stock_uom: Mapped[Optional[str]] = mapped_column(String(5)) # UMEXISTENCIA
    alternate_uom: Mapped[Optional[str]] = mapped_column(String(5)) # UNIMEDALTERNA
    conversion_uom: Mapped[Optional[str]] = mapped_column(String(9)) # UMCONVERSION

    # Valor Agregado
    added_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # VALORAGREGADO
    added_value_type: Mapped[Optional[str]] = mapped_column(String(2)) # TIPOVA

    assigned_client: Mapped[Optional[str]] = mapped_column(String(50)) # CLIENTEASIGNADO
    supplier_code: Mapped[Optional[str]] = mapped_column(String(8)) # PROVEEDOR
    is_textile: Mapped[Optional[str]] = mapped_column(String(2)) # ESTEXTIL

    # --- 2. MANUFACTURA Y PELIGROSIDAD ---
    bom_version: Mapped[Optional[int]] = mapped_column(Integer) # VERSIONBOM / VERSIONBILL
    is_repair: Mapped[Optional[str]] = mapped_column(String(3)) # ESREPARACION
    is_hazardous: Mapped[Optional[str]] = mapped_column(String(1)) # ESMATPELIGROSO
    
    emergency_number: Mapped[Optional[str]] = mapped_column(String(30)) # NUMEMERGENCIA
    danger_class: Mapped[Optional[str]] = mapped_column(String(4)) # CLASEDEPELIGRO
    packaging_group: Mapped[Optional[str]] = mapped_column(String(3)) # GRUPOEMBALAJE

    # Dimensiones
    width: Mapped[Optional[str]] = mapped_column(String(50)) # ANCHURA
    thickness: Mapped[Optional[str]] = mapped_column(String(50)) # ESPESOR
    specification: Mapped[Optional[str]] = mapped_column(String(50)) # SPEC

    # --- 3. COSTOS DETALLADOS Y ADUANA US ---
    total_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # VALORTOTAL
    direct_labor: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # TRABAJODIREC
    general_expenses: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # GASTOGRALES
    total_expenses: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # TOTALGASTOS
    
    depreciation: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # DEPRECIACION
    tooling: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # TOOLING
    material_consumed: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # MATCONSUMED
    profit: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8)) # GANANCIA

    # Fracciones Internacionales
    us_fraction_alt: Mapped[Optional[str]] = mapped_column(String(13)) # FRACEUA
    ca_fraction: Mapped[Optional[str]] = mapped_column(String(13)) # FRACCANADA
    ad_valorem_us: Mapped[Optional[Decimal]] = mapped_column(Numeric(5, 2)) # ADVALOREMAME

    # Nafta / USMCA
    nafta_result: Mapped[Optional[str]] = mapped_column(String(19)) # RESULTADOCALCULONAFTA
    nafta_percentage: Mapped[Optional[Decimal]] = mapped_column(Numeric(5, 2)) # PORCENTAJECALCULONAFTA

    # Impuestos Específicos (Derechos de Trámite Admon)
    dta: Mapped[Optional[str]] = mapped_column(String(19)) # DTA
    dtb: Mapped[Optional[str]] = mapped_column(String(19)) # DTB
    dtg: Mapped[Optional[str]] = mapped_column(String(19)) # DTG

    # --- CAMPOS ADICIONALES FRONTEND ---
    substitute_part: Mapped[Optional[str]] = mapped_column(String(70))
    complementary_part: Mapped[Optional[str]] = mapped_column(String(70))
    preference_part: Mapped[Optional[str]] = mapped_column(String(70))
    use_alternate_quantity: Mapped[Optional[bool]] = mapped_column(Boolean, default=False)
    un_number: Mapped[Optional[str]] = mapped_column(String(30))
    shipping_name: Mapped[Optional[str]] = mapped_column(String(200))
    hazard_notes: Mapped[Optional[str]] = mapped_column(String(500))
    repair_unit_cost: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
    repair_added_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
    fraction_9801: Mapped[Optional[str]] = mapped_column(String(10))
    immex_type: Mapped[Optional[str]] = mapped_column(String(10))
    disable_movements: Mapped[Optional[bool]] = mapped_column(Boolean, default=False)
    pga_program_code: Mapped[Optional[str]] = mapped_column(String(10))
    usmca_fraction: Mapped[Optional[str]] = mapped_column(String(10))
    scrap_part_number: Mapped[Optional[str]] = mapped_column(String(70))
    waste_part_number: Mapped[Optional[str]] = mapped_column(String(70))
    scrap_description_en: Mapped[Optional[str]] = mapped_column(String(500))
    scrap_description_es: Mapped[Optional[str]] = mapped_column(String(500))
    scrap_export_fraction: Mapped[Optional[str]] = mapped_column(String(10))
    scrap_us_fraction: Mapped[Optional[str]] = mapped_column(String(10))
    equivalent_uom_2: Mapped[Optional[str]] = mapped_column(String(5))
    conversion_factor_2: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 8))
    has_auxiliary: Mapped[Optional[bool]] = mapped_column(Boolean, default=False)
    auxiliary_uom: Mapped[Optional[str]] = mapped_column(String(5))
    auxiliary_conversion: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 8))
    auxiliary_unit_cost: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
    mex_packing: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
    sales_order: Mapped[Optional[str]] = mapped_column(String(50))
    use_rule_8: Mapped[Optional[bool]] = mapped_column(Boolean, default=False)
    sector: Mapped[Optional[str]] = mapped_column(String(150))
    origin_country: Mapped[Optional[str]] = mapped_column(String(3), default='MEX')
    fraction_type: Mapped[Optional[str]] = mapped_column(String(10))

    # --- NUEVOS CAMPOS EXTENSION ---
    agency_code_definition: Mapped[Optional[str]] = mapped_column(String(50)) # Fila 7
    carta_porte: Mapped[Optional[str]] = mapped_column(String(100)) # Fila 10
    
    client_part_names: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True, default=[]) # Fila 5
    part_identifiers: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True, default=[]) # Fila 9
    substitute_parts: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True, default=[]) # Pestaña Continuación
    aphis_data: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True, default={}) # Sección Aphis en Continuación

    # JSONB para almacenar clientes con restricción de no descarga
    non_discharge_clients: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True, default=[])

    # --- RELACIÓN ---
    aphis_records: Mapped[List["InvPartAphisGeneral"]] = relationship(
        "InvPartAphisGeneral", 
        back_populates="inv_part", 
        cascade="all, delete-orphan"
    )
    # Usamos string "Part" para evitar problemas de carga
    master_info: Mapped["Part"] = relationship("Part", back_populates="inv_data")

    @property
    def bom_items(self):
        """Exponer los BOM items de la parte maestra para Pydantic"""
        if self.master_info:
            return self.master_info.bom_items
        return []

    @property
    def countries(self):
        """Exponer los países de la parte maestra para Pydantic"""
        if self.master_info:
            return self.master_info.inv_countries
        return []

    def __repr__(self) -> str:
        return f"<InvPart(id={self.id}, part_type='{self.part_type}')>"