"""
Split Calculator Module
Handles splitting logic and calculations.
"""

from decimal import Decimal
from typing import Dict, List
from .expense_calculator import ExpenseCalculator, SplitMethod


class SplitCalculator:
    """Calculator for expense splits."""
    
    @staticmethod
    def calculate_balances(
        expenses: List[Dict],
        paid_by_field: str = "paid_by",
        amount_field: str = "amount",
        participants_field: str = "participants"
    ) -> Dict[str, Decimal]:
        """
        Calculate net balances for each user.
        
        Args:
            expenses: List of expense dictionaries
            paid_by_field: Field name for who paid
            amount_field: Field name for amount
            participants_field: Field name for participants
        
        Returns:
            Dictionary mapping user_id to net balance (positive = owes, negative = is owed)
        """
        balances = {}
        
        for expense in expenses:
            paid_by = expense.get(paid_by_field)
            amount = Decimal(str(expense.get(amount_field, 0)))
            participants = expense.get(participants_field, [])
            split_method = SplitMethod(expense.get("split_method", "equal"))
            participant_data = expense.get("participant_data", {})
            
            # Calculate splits
            splits = ExpenseCalculator.calculate_split(
                amount,
                participants,
                split_method,
                participant_data
            )
            
            # Update balances
            # Person who paid gets credited
            if paid_by not in balances:
                balances[paid_by] = Decimal(0)
            balances[paid_by] -= amount
            
            # Participants owe their share
            for participant, share in splits.items():
                if participant not in balances:
                    balances[participant] = Decimal(0)
                balances[participant] += share
        
        return balances
    
    @staticmethod
    def calculate_settlements(balances: Dict[str, Decimal]) -> List[Dict]:
        """
        Calculate minimum number of settlements to balance all debts.
        Uses a greedy algorithm.
        
        Args:
            balances: Dictionary mapping user_id to net balance
        
        Returns:
            List of settlement dictionaries with 'from', 'to', and 'amount'
        """
        # Separate debtors and creditors
        debtors = {user: -balance for user, balance in balances.items() if balance < 0}
        creditors = {user: balance for user, balance in balances.items() if balance > 0}
        
        settlements = []
        
        # Greedy settlement algorithm
        while debtors and creditors:
            # Find largest debtor and creditor
            max_debtor = max(debtors.items(), key=lambda x: x[1])
            max_creditor = max(creditors.items(), key=lambda x: x[1])
            
            debtor_user, debtor_amount = max_debtor
            creditor_user, creditor_amount = max_creditor
            
            # Calculate settlement amount
            settlement_amount = min(debtor_amount, creditor_amount)
            
            settlements.append({
                "from": debtor_user,
                "to": creditor_user,
                "amount": float(settlement_amount)
            })
            
            # Update balances
            debtor_amount -= settlement_amount
            creditor_amount -= settlement_amount
            
            if debtor_amount <= Decimal("0.01"):
                del debtors[debtor_user]
            else:
                debtors[debtor_user] = debtor_amount
            
            if creditor_amount <= Decimal("0.01"):
                del creditors[creditor_user]
            else:
                creditors[creditor_user] = creditor_amount
        
        return settlements

