"""
Exchange rate calculation logic for invoice movements.
"""

import logging
from sqlalchemy.orm import Session
from typing import Tuple, Optional
from .base import DateHelper
from .database_helpers import DatabaseHelper

logger = logging.getLogger(__name__)


class ExchangeRateCalculator:
    """Handles exchange rate calculations and commercial value conversions."""
    
    @staticmethod
    def calculate_exchange_rate_and_value(
        db: Session,
        db_name: str,
        es_subpartida: str,
        valor_me: Optional[float],
        valor_mn_direct: Optional[float],
        fecha_pago,
        fecha_inicio,
        clave_ped: str,
        tipo_cambio_partida: Optional[float],
        currency_type: str,
        exchange_rate_type: str,
        met_trans: int
    ) -> Tuple[float, Optional[float]]:
        """
        Unified method to calculate exchange rate and commercial value.
        Eliminates duplicated logic across all import types.
        
        Args:
            db: Database session
            db_name: Database name
            es_subpartida: Subpartida flag ('P' for partida, 'S' for subpartida)
            valor_me: Value in foreign currency (ME)
            valor_mn_direct: Direct value in local currency (MN)
            fecha_pago: Payment date
            fecha_inicio: Start/entry date
            clave_ped: Pedimento type code
            tipo_cambio_partida: Exchange rate from partida record
            currency_type: "ME" or "MN"
            exchange_rate_type: "FP" (payment date) or "FT" (transaction date)
            met_trans: MetTrans configuration value
            
        Returns:
            Tuple of (valor_comercial_mn, tipo_cambio_final)
        """
        # Handle subpartidas - always return zero
        if es_subpartida == 'S':
            return (0.0, None)
        
        # Handle foreign currency (ME) case
        if currency_type == "ME":
            valor_comercial = valor_me or 0.0
            tipo_cambio_final = tipo_cambio_partida
            
            # Try to get exchange rate from GTipoCambio if using payment date
            if exchange_rate_type == "FP" and fecha_pago:
                fecha_tc = DateHelper.get_fecha_tipo_cambio(
                    fecha_pago=fecha_pago,
                    fecha_inicio=fecha_inicio,
                    tipo_pedimento=clave_ped,
                    use_transport_method=True,
                    met_trans=met_trans
                )
                tc_value = DatabaseHelper.get_exchange_rate(db, db_name, fecha_tc)
                if tc_value:
                    tipo_cambio_final = tc_value
            
            # For ME, the value is always in foreign currency (USD)
            return (valor_comercial, tipo_cambio_final)
        
        # Handle local currency (MN) case
        if exchange_rate_type == "FP" and fecha_pago:
            fecha_tc = DateHelper.get_fecha_tipo_cambio(
                fecha_pago=fecha_pago,
                fecha_inicio=fecha_inicio,
                tipo_pedimento=clave_ped,
                use_transport_method=True,
                met_trans=met_trans
            )
            tc_value = DatabaseHelper.get_exchange_rate(db, db_name, fecha_tc)
            
            if tc_value and valor_me is not None:
                # Calculate MN value from ME * payment date exchange rate
                return (valor_me * tc_value, tc_value)
            else:
                if tc_value is None:
                    logger.warning(f"Exchange rate not found for date {fecha_tc}, using partida values")
                return (valor_mn_direct or 0.0, tipo_cambio_partida)
        else:
            # exchange_rate_type == "FT" (Invoice Date)
            # Use direct MN value and partida exchange rate
            return (valor_mn_direct or 0.0, tipo_cambio_partida)
    
    @staticmethod
    def calculate_for_aggregated(
        db: Session,
        db_name: str,
        valor_me: float,
        valor_mn: float,
        tipo_cambio_db: float,
        fecha_pago,
        fecha_inicio,
        tipo_pedimento: str,
        currency_type: str,
        exchange_rate_type: str,
        is_shelter: bool,
        use_transport_method: bool,
        met_trans: int
    ) -> Tuple[float, Optional[float]]:
        """
        Calculate exchange rate and value for aggregated (normal mode) movements.
        
        This method is used when movements are grouped by invoice rather than
        showing individual partidas.
        
        Args:
            db: Database session
            db_name: Database name
            valor_me: Aggregated value in foreign currency
            valor_mn: Aggregated value in local currency
            tipo_cambio_db: Exchange rate from database
            fecha_pago: Payment date
            fecha_inicio: Start date
            tipo_pedimento: Pedimento type
            currency_type: "ME" or "MN"
            exchange_rate_type: "FP" or "FT"
            is_shelter: Shelter company flag (kept for compatibility)
            use_transport_method: Use transport method flag
            met_trans: MetTrans value from config
            
        Returns:
            Tuple of (valor_comercial_mn, tipo_cambio)
        """
        # Foreign currency case
        if currency_type == "ME":
            valor_comercial = valor_me
            tipo_cambio = tipo_cambio_db
            
            # Try to get exchange rate if using payment date
            if exchange_rate_type == "FP" and fecha_pago:
                fecha_tc = DateHelper.get_fecha_tipo_cambio(
                    fecha_pago=fecha_pago,
                    fecha_inicio=fecha_inicio,
                    tipo_pedimento=tipo_pedimento,
                    use_transport_method=use_transport_method,
                    met_trans=met_trans
                )
                tc_value = DatabaseHelper.get_exchange_rate(
                    db, db_name, fecha_tc, 
                    is_shelter=is_shelter,
                    raise_on_missing=is_shelter
                )
                
                if tc_value:
                    # For ME, the value is always in foreign currency (USD). Just return the new exchange rate.
                    return (valor_comercial, tc_value)
                else:
                    logger.warning(f"Exchange rate not found for date {fecha_tc}, using DB values")
            
            return (valor_comercial, tipo_cambio)
            
        # Local currency case
        else:
            if exchange_rate_type == "FP" and fecha_pago:
                fecha_tc = DateHelper.get_fecha_tipo_cambio(
                    fecha_pago=fecha_pago,
                    fecha_inicio=fecha_inicio,
                    tipo_pedimento=tipo_pedimento,
                    use_transport_method=use_transport_method,
                    met_trans=met_trans
                )
                tc_value = DatabaseHelper.get_exchange_rate(
                    db, db_name, fecha_tc, 
                    is_shelter=is_shelter,
                    raise_on_missing=is_shelter
                )
                
                if tc_value and valor_me is not None:
                    # Calculate MN value from ME * payment date exchange rate
                    return (valor_me * tc_value, tc_value)
                else:
                    if tc_value is None:
                        logger.warning(f"Exchange rate not found for date {fecha_tc}, using DB values")
                    return (valor_mn, tipo_cambio_db)
            else:
                return (valor_mn, tipo_cambio_db)
