"""
Unified service for invoice movement operations.
This service delegates to specialized handlers for each import type.
"""

import logging
from sqlalchemy.orm import Session
from typing import List

from .schemas import (
    ImportTemporaryFilter,
    ImportDefinitiveFilter,
    ImportRepairFilter,
    ExportFilter,
    ExportRepairFilter,
    AllMovementsFilter,
    MovementItem,
    MovementItemDetailed,
    ReportType
)
from .services.temporary import TemporaryImportService
from .services.definitive import DefinitiveImportService
from .services.repair import RepairImportService
from .services.export import ExportService
from .services.export_repair import ExportRepairService

logger = logging.getLogger(__name__)


class MovementService:
    """
    Unified service for handling all types of movements.
    Delegates to specialized services for each movement type.
    """
    
    def __init__(self):
        self.temporary_service = TemporaryImportService()
        self.definitive_service = DefinitiveImportService()
        self.repair_service = RepairImportService()
        self.export_service = ExportService()
        self.export_repair_service = ExportRepairService()
    
    # ===== TEMPORARY IMPORTS =====
    
    def get_temporary_import_movements(
        self,
        db: Session,
        filters: ImportTemporaryFilter
    ) -> List[MovementItem]:
        """Get temporary import movements (normal mode - grouped by invoice)."""
        return self.temporary_service.get_movements(db, filters)
    
    def get_temporary_import_movements_detailed(
        self,
        db: Session,
        filters: ImportTemporaryFilter
    ) -> List[MovementItemDetailed]:
        """Get temporary import movements (detailed mode - line by line)."""
        return self.temporary_service.get_movements_detailed(db, filters)
    
    # ===== DEFINITIVE IMPORTS =====
    
    def get_definitive_import_movements(
        self,
        db: Session,
        filters: ImportDefinitiveFilter
    ) -> List[MovementItem]:
        """Get definitive import movements (normal mode - grouped by invoice)."""
        return self.definitive_service.get_movements(db, filters)
    
    def get_definitive_import_movements_detailed(
        self,
        db: Session,
        filters: ImportDefinitiveFilter
    ) -> List[MovementItemDetailed]:
        """Get definitive import movements (detailed mode - line by line)."""
        return self.definitive_service.get_movements_detailed(db, filters)
    
    # ===== REPAIR IMPORTS =====
    
    def get_repair_import_movements(
        self,
        db: Session,
        filters: ImportRepairFilter
    ) -> List[MovementItem]:
        """Get repair import movements (normal mode - grouped by invoice)."""
        return self.repair_service.get_movements(db, filters)
    
    def get_repair_import_movements_detailed(
        self,
        db: Session,
        filters: ImportRepairFilter
    ) -> List[MovementItemDetailed]:
        """Get repair import movements (detailed mode - line by line)."""
        return self.repair_service.get_movements_detailed(db, filters)
    
    # ===== EXPORTS =====
    
    def get_export_movements(
        self,
        db: Session,
        filters: ExportFilter
    ) -> List[MovementItem]:
        """Get export movements (normal mode - grouped by invoice)."""
        return self.export_service.get_movements(db, filters)
    
    def get_export_movements_detailed(
        self,
        db: Session,
        filters: ExportFilter
    ) -> List[MovementItemDetailed]:
        """Get export movements (detailed mode - line by line)."""
        return self.export_service.get_movements_detailed(db, filters)
    
    # ===== EXPORT REPAIRS =====
    
    def get_export_repair_movements(
        self,
        db: Session,
        filters: ExportRepairFilter
    ) -> List[MovementItem]:
        """Get export repair movements (normal mode - grouped by invoice)."""
        return self.export_repair_service.get_movements(db, filters)
    
    def get_export_repair_movements_detailed(
        self,
        db: Session,
        filters: ExportRepairFilter
    ) -> List[MovementItemDetailed]:
        """Get export repair movements (detailed mode - line by line)."""
        return self.export_repair_service.get_movements_detailed(db, filters)
    
    # ===== ALL MOVEMENTS =====
    
    def get_all_movements(
        self,
        db: Session,
        filters: AllMovementsFilter
    ) -> List[MovementItem]:
        """
        Get all invoice movements (all types combined).
        
        This combines:
        - Temporary imports
        - Definitive imports
        - Repair imports  
        - All export types
        - Export repairs
        
        Returns a unified list sorted by date.
        """
        all_movements = []
        
        # Convert AllMovementsFilter to individual filter types
        # We'll use the same filter parameters for all queries
        
        # Determine which services to call based on granular flags
        # Default behavior: If granular flags are all defaults (True) but operation_type is set, 
        # we might need to respect operation_type.
        # But for simplicity, we assume granular flags from frontend are the source of truth.
        # If frontend didn't set them (legacy call?), they default to True.
        
        # Override based on operation_type if provided (legacy compatibility or coarse filter)
        if filters.operation_type == 'imp':
            filters.export_def = False
            filters.export_rep = False
        elif filters.operation_type == 'exp':
            filters.import_temp = False
            filters.import_def = False
            filters.import_rep = False
            
        logger.info(f"Fetching movements with flags: Temp={filters.import_temp}, Def={filters.import_def}, Rep={filters.import_rep}, ExpDef={filters.export_def}, ExpRep={filters.export_rep}")
        
        # 1. Temporary Imports
        if filters.import_temp:
                temp_filter = ImportTemporaryFilter(
                    range_type=filters.range_type,
                    start_date=filters.start_date,
                    end_date=filters.end_date,
                    include_cancelled=filters.include_cancelled,
                    provider=filters.provider,
                    buyer=filters.buyer,
                    pedimento_code=filters.pedimento_code,
                    report_type=filters.report_type,
                    currency_type=filters.currency_type,
                    exchange_rate_type=filters.exchange_rate_type,
                    is_shelter=filters.is_shelter,
                    database_name='default'
                )
                if filters.report_type == ReportType.DETAILED:
                    temp_movements = self.temporary_service.get_movements_detailed(db, temp_filter)
                else:
                    temp_movements = self.temporary_service.get_movements(db, temp_filter)
                all_movements.extend(temp_movements)
                logger.info(f"Added {len(temp_movements)} temporary import movements")
        
        # 2. Definitive Imports
        if filters.import_def:
            def_filter = ImportDefinitiveFilter(
                range_type=filters.range_type,
                start_date=filters.start_date,
                end_date=filters.end_date,
                include_cancelled=filters.include_cancelled,
                provider=filters.provider,
                buyer=filters.buyer,
                pedimento_code=filters.pedimento_code,
                report_type=filters.report_type,
                currency_type=filters.currency_type,
                exchange_rate_type=filters.exchange_rate_type,
                is_shelter=filters.is_shelter,
                database_name='default',
                movement_type='ALL',
                use_transport_method=False
            )
            if filters.report_type == ReportType.DETAILED:
                def_movements = self.definitive_service.get_movements_detailed(db, def_filter)
            else:
                def_movements = self.definitive_service.get_movements(db, def_filter)
            all_movements.extend(def_movements)
            logger.info(f"Added {len(def_movements)} definitive import movements")
        
        # 3. Repair Imports
        if filters.import_rep:
            repair_filter = ImportRepairFilter(
                range_type=filters.range_type,
                start_date=filters.start_date,
                end_date=filters.end_date,
                include_cancelled=filters.include_cancelled,
                provider=filters.provider,
                buyer=filters.buyer,
                pedimento_code=filters.pedimento_code,
                report_type=filters.report_type,
                currency_type=filters.currency_type,
                exchange_rate_type=filters.exchange_rate_type,
                is_shelter=filters.is_shelter,
                database_name='default',
                discharge_filter='ALL',
                use_transport_method=False
            )
            if filters.report_type == ReportType.DETAILED:
                repair_movements = self.repair_service.get_movements_detailed(db, repair_filter)
            else:
                repair_movements = self.repair_service.get_movements(db, repair_filter)
            all_movements.extend(repair_movements)
            logger.info(f"Added {len(repair_movements)} repair import movements")
        
        # 4. Exports (Definitive)
        if filters.export_def:
            export_filter = ExportFilter(
                range_type=filters.range_type,
                start_date=filters.start_date,
                end_date=filters.end_date,
                include_cancelled=filters.include_cancelled,
                provider=filters.provider,
                buyer=filters.buyer,
                pedimento_code=filters.pedimento_code,
                report_type=filters.report_type,
                currency_type=filters.currency_type,
                exchange_rate_type=filters.exchange_rate_type,
                is_shelter=filters.is_shelter,
                database_name='default',
                movement_type='ALL',
                discharge_filter='ALL',
                use_transport_method=False
            )
            if filters.report_type == ReportType.DETAILED:
                export_movements = self.export_service.get_movements_detailed(db, export_filter)
            else:
                export_movements = self.export_service.get_movements(db, export_filter)
            all_movements.extend(export_movements)
            logger.info(f"Added {len(export_movements)} export movements")
        
        # 5. Export Repairs
        if filters.export_rep:
            export_repair_filter = ExportRepairFilter(
                range_type=filters.range_type,
                start_date=filters.start_date,
                end_date=filters.end_date,
                include_cancelled=filters.include_cancelled,
                provider=filters.provider,
                buyer=filters.buyer,
                pedimento_code=filters.pedimento_code,
                report_type=filters.report_type,
                currency_type=filters.currency_type,
                exchange_rate_type=filters.exchange_rate_type,
                is_shelter=filters.is_shelter,
                database_name='default',
                movement_type='ALL',
                discharge_filter='ALL'
            )
            if filters.report_type == ReportType.DETAILED:
                export_repair_movements = self.export_repair_service.get_movements_detailed(db, export_repair_filter)
            else:
                export_repair_movements = self.export_repair_service.get_movements(db, export_repair_filter)
            all_movements.extend(export_repair_movements)
            logger.info(f"Added {len(export_repair_movements)} export repair movements")
        
        # Sort all movements by date (Fecha field)
        # Handle mixed datetime and string types
        def get_sort_key(movement):
            fecha = movement.FechaFactura
            if not fecha:
                return ""
            # Convert datetime to string for consistent comparison
            if hasattr(fecha, 'strftime'):
                return fecha.strftime('%Y%m%d')
            return str(fecha)
        
        all_movements.sort(key=get_sort_key)
        
        logger.info(f"Total movements combined: {len(all_movements)}")
        return all_movements


# Singleton instance
movement_service = MovementService()
