
from typing import List
from sqlalchemy.orm import Session

# Import Reference Data Models
from api.v1.modules.public.reference_data.pedimento_codes.models import PedimentoCode
from api.v1.modules.public.reference_data.customs_sections.models import CustomsSection
from api.v1.modules.public.reference_data.code_pedimento_regimens.models import CodePedimentoRegimen
from api.v1.modules.public.reference_data.transport_types.models import TransportType
from api.v1.modules.public.reference_data.transport_modes.models import TransportMode
from api.v1.modules.public.reference_data.pedimento_transport_catalog.models import (
    PedimentoTransportCatalog,
)

# Import A76 Services
from api.v1.modules.a76.customs_brokers.services import CustomsBrokerService
from api.v1.modules.a76.clients_and_providers.service import ClientProviderService

# Import DTOs for mapping
from api.v1.modules.public.reference_data.pedimento_codes.dto import PedimentoCodeDTO
from api.v1.modules.public.reference_data.customs_sections.dto import CustomsSectionDTO
from api.v1.modules.public.reference_data.code_pedimento_regimens.dto import CodePedimentoRegimenDTO
from api.v1.modules.public.reference_data.transport_types.dto import TransportTypeDTO
from api.v1.modules.public.reference_data.transport_modes.dto import TransportModeDTO
from api.v1.modules.public.reference_data.pedimento_transport_catalog.dto import (
    PedimentoTransportCatalogDTO,
)
from api.v1.modules.a76.customs_brokers.dto import CustomsBrokerResponseDTO
from api.v1.modules.a76.clients_and_providers.dto import ClientProviderResponseDTO
from .dtos.pedimentos import PedimentosResponse

from .schemas import PedimentoCatalogsResponse, PedimentoCreationResponse, PedimentoEditionResponse

class PedimentoCatalogService:
    """Service to fetch consolidated catalogs for Pedimento views"""

    @staticmethod
    def get_catalogs(db: Session, tenant_id: int, company_id: int) -> PedimentoCatalogsResponse:
        """Fetch all catalogs with graceful degradation"""
        
        response = PedimentoCatalogsResponse()

        # Helper to fetch reference data (no company_id needed)
        def fetch_ref_data():
            try:
                response.pedimento_codes = [
                    PedimentoCodeDTO.model_validate(obj) for obj in db.query(PedimentoCode).limit(100).all()
                ]
            except Exception as e:
                print(f"Error fetching pedimento_codes: {e}")
                
            try:
                response.customs_sections = [
                    CustomsSectionDTO.model_validate(obj) for obj in db.query(CustomsSection).limit(100).all()
                ]
            except Exception as e:
                print(f"Error fetching customs_sections: {e}")
                
            try:
                response.code_pedimento_regimens = [
                    CodePedimentoRegimenDTO.model_validate(obj) for obj in db.query(CodePedimentoRegimen).limit(100).all()
                ]
            except Exception as e:
                print(f"Error fetching code_pedimento_regimens: {e}")

            try:
                response.transport_types = [
                    TransportTypeDTO.model_validate(obj) for obj in db.query(TransportType).limit(200).all()
                ]
            except Exception as e:
                print(f"Error fetching transport_types: {e}")

            try:
                response.transport_modes = [
                    TransportModeDTO.model_validate(obj) for obj in db.query(TransportMode).limit(100).all()
                ]
            except Exception as e:
                print(f"Error fetching transport_modes: {e}")

            try:
                response.pedimento_transport_catalog = [
                    PedimentoTransportCatalogDTO.model_validate(obj)
                    for obj in db.query(PedimentoTransportCatalog)
                    .order_by(PedimentoTransportCatalog.code.asc())
                    .all()
                ]
            except Exception as e:
                print(f"Error fetching pedimento_transport_catalog: {e}")

        # Helper to fetch tenant/company specific data
        def fetch_tenant_data():
            # Customs Brokers
            try:
                brokers, _ = CustomsBrokerService.get_all(db, tenant_id, company_id, limit=1000)
                response.customs_brokers = [
                    CustomsBrokerResponseDTO.model_validate(obj) for obj in brokers
                ]
            except Exception as e:
                print(f"Error fetching customs brokers: {e}")

            # Clients (only clients, not providers)
            try:
                all_cps, _ = ClientProviderService.get_all(
                    db, tenant_id, company_id, limit=1000
                )
                
                # Helper to safely check client type (handles string or Enum)
                def is_type(obj, types):
                    val = obj.client_or_provider
                    # If it's an enum, get its value, otherwise use as string
                    val_str = val.value if hasattr(val, 'value') else str(val)
                    return val_str in types

                response.clients = [
                    ClientProviderResponseDTO.model_validate(obj) for obj in all_cps 
                    if is_type(obj, ['client', 'both'])
                ]
            except Exception as e:
                print(f"Error fetching clients: {e}")

        try:
            fetch_ref_data()
            fetch_tenant_data()
        except Exception as e:
            print(f"Error fetching catalogs: {e}")
            import traceback
            traceback.print_exc()
            raise e
        
        return response

    @staticmethod
    def get_creation_data(db: Session, tenant_id: int, company_id: int) -> PedimentoCreationResponse:
        catalogs = PedimentoCatalogService.get_catalogs(db, tenant_id, company_id)
        return PedimentoCreationResponse(
            **catalogs.model_dump(),
            is_create=True
        )

    @staticmethod
    def get_edition_data(db: Session, pedimento_id: int, tenant_id: int, company_id: int) -> PedimentoEditionResponse:
        catalogs = PedimentoCatalogService.get_catalogs(db, tenant_id, company_id)
        
        from .services.pedimentos import PedimentosService
        pedimento = PedimentosService.get_by_id(db, pedimento_id, tenant_id, company_id)
        
        if not pedimento:
            return None
        
        # Convert SQLAlchemy object to Pydantic DTO
        pedimento_dto = PedimentosResponse.model_validate(pedimento)
            
        return PedimentoEditionResponse(
            **catalogs.model_dump(),
            is_create=False,
            pedimento=pedimento_dto,
            pedimento_id=pedimento_id
        )
