"""
Modelos ORM para gestión de partes/componentes - Anexo 76 (Master Data)
"""

from datetime import datetime
from decimal import Decimal
from typing import TYPE_CHECKING, Optional, List

from api.v1.common.base_models import TenantScopedMixin, TimestampMixin
from core.database import Base
from sqlalchemy import (
    ForeignKeyConstraint,
    Integer,
    Numeric,
    PrimaryKeyConstraint,
    String,
    UniqueConstraint,
    Boolean,
    DateTime,
)

# Importante usar relationship y Mapped
from sqlalchemy.orm import Mapped, mapped_column, relationship

from api.v1.modules.public.reference_data.currency_types.models import CurrencyType
from api.v1.modules.a24.fa.fa_parts.models import FaPart
from api.v1.modules.a24.inv.inv_parts.models import InvPart
from api.v1.modules.a24.inv.bom.models import BillOfMaterial
from api.v1.modules.a24.inv.part_countries.models import PartCountry


if TYPE_CHECKING:
    from api.v1.modules.a76.classes.models import Class
    from api.v1.modules.a76.general_catalogs.units_of_measure.models import (
        UnitOfMeasure,
    )


class Part(Base, TenantScopedMixin, TimestampMixin):
    __tablename__ = "parts"
    __table_args__ = (
        PrimaryKeyConstraint("id", name="parts_pkey"),
        ForeignKeyConstraint(
            ["currency_key"], ["public.currency_types.code"], name="fk_parts_currency"
        ),
        ForeignKeyConstraint(
            ["unit_of_measure", "tenant_id", "company_id"],
            [
                "a76.units_of_measure.code",
                "a76.units_of_measure.tenant_id",
                "a76.units_of_measure.company_id",
            ],
        ),
        # Puente hacia la tabla de clases
        ForeignKeyConstraint(
            ["part_class", "tenant_id", "company_id"],
            [
                "a76.classes.class_code",
                "a76.classes.tenant_id",
                "a76.classes.company_id",
            ],
            name="fk_parts_class",
        ),
        UniqueConstraint(
            "tenant_id", "company_id", "part_number", name="client_part_ukey"
        ),
        {"schema": "a76"},
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    part_number: Mapped[str] = mapped_column(String(70))
    commercial_part_number: Mapped[Optional[str]] = mapped_column(String(70))

    description_spanish: Mapped[Optional[str]] = mapped_column(String(500))
    description_english: Mapped[Optional[str]] = mapped_column(String(500))
    part_class: Mapped[Optional[str]] = mapped_column(String(8))
    unit_of_measure: Mapped[Optional[str]] = mapped_column(String(5))

    unit_cost: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
    currency_type: Mapped[Optional[str]] = mapped_column(String(2))
    currency_key: Mapped[Optional[str]] = mapped_column(String(3))

    unit_weight: Mapped[Optional[Decimal]] = mapped_column(Numeric(19, 8))
    weight_type: Mapped[Optional[str]] = mapped_column(String(6))

    fraction: Mapped[Optional[str]] = mapped_column(String(10))
    us_fraction: Mapped[Optional[str]] = mapped_column(String(16))
    fda_key: Mapped[Optional[str]] = mapped_column(String(20))
    fcc_key: Mapped[Optional[str]] = mapped_column(String(30))
    license_code: Mapped[Optional[str]] = mapped_column(String(3))
    eccn: Mapped[Optional[str]] = mapped_column(String(20))
    export_code: Mapped[Optional[str]] = mapped_column(String(2))
    exclusion_symbol: Mapped[Optional[str]] = mapped_column(String(19))

    is_active: Mapped[Optional[bool]] = mapped_column(
        Boolean, default=True, server_default="true"
    )
    part_photo: Mapped[Optional[str]] = mapped_column(String(255))

    creation_date: Mapped[Optional[int]] = mapped_column()
    modification_date: Mapped[Optional[int]] = mapped_column()
    modification_date_iso: Mapped[Optional[datetime]] = mapped_column(DateTime)

    # --- RELACIONES ---
    currency: Mapped[Optional["CurrencyType"]] = relationship("CurrencyType")
    unit_of_measure_info: Mapped[Optional["UnitOfMeasure"]] = relationship(
        "UnitOfMeasure"
    )
    part_class_info: Mapped[Optional["Class"]] = relationship(
        "Class", back_populates="parts", overlaps="unit_of_measure_info"
    )

    # Extensiones Anexo 24
    fa_data: Mapped[Optional["FaPart"]] = relationship(
        "FaPart",
        back_populates="master_info",
        uselist=False,
        cascade="all, delete-orphan",
    )
    inv_data: Mapped[Optional["InvPart"]] = relationship(
        "InvPart",
        back_populates="master_info",
        uselist=False,
        cascade="all, delete-orphan",
    )

    # Bom Components (as parent)
    bom_items: Mapped[List["BillOfMaterial"]] = relationship(
        "BillOfMaterial",
        foreign_keys=[BillOfMaterial.parent_part_id],
        cascade="all, delete-orphan",
        back_populates="parent_part"
    )

    # Países Anexo 24
    inv_countries: Mapped[List["PartCountry"]] = relationship(
        "PartCountry",
        cascade="all, delete-orphan",
        back_populates="part"
    )

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