"""
Split engine for TripTalley expenses.
Handles equal, custom, and percentage splits with largest-remainder rounding.
All money amounts are in integer minor units.
"""

from typing import Dict, List, Tuple
from .money import split_equal, split_percentage, split_custom, Money


class SplitEngine:
    """
    Performs expense splits using various strategies with deterministic rounding.
    """
    
    @staticmethod
    def split_equal(total: Money, participant_ids: List[int]) -> Dict[int, Money]:
        """
        Split an expense equally among participants.
        
        Args:
            total: The total expense amount
            participant_ids: List of user IDs who are sharing the expense
            
        Returns:
            Dict mapping user_id to their share as a Money amount
        """
        if not participant_ids:
            return {}
        
        shares_minor = split_equal(total.amount_minor, participant_ids)
        return {user_id: Money(amount, total.currency) 
                for user_id, amount in shares_minor.items()}
    
    @staticmethod
    def split_percentage(total: Money, 
                        participant_weights: List[Tuple[int, int]]) -> Dict[int, Money]:
        """
        Split an expense by percentage weights.
        
        Args:
            total: The total expense amount
            participant_weights: List of (user_id, weight_in_basis_points)
                                Weights must sum to 10000
        
        Returns:
            Dict mapping user_id to their share as a Money amount
            
        Raises:
            ValueError: If weights don't sum to 10000
        """
        if not participant_weights:
            return {}
        
        shares_minor = split_percentage(total.amount_minor, participant_weights)
        return {user_id: Money(amount, total.currency) 
                for user_id, amount in shares_minor.items()}
    
    @staticmethod
    def split_custom(total: Money, 
                    participant_amounts: List[Tuple[int, int]]) -> Dict[int, Money]:
        """
        Custom split where each participant specifies their exact share.
        
        Args:
            total: The total expense amount
            participant_amounts: List of (user_id, exact_minor_amount)
                                Amounts must sum to total.amount_minor
        
        Returns:
            Dict mapping user_id to their share as a Money amount
            
        Raises:
            ValueError: If amounts don't sum to total
        """
        if not participant_amounts:
            return {}
        
        shares_minor = split_custom(total.amount_minor, participant_amounts)
        return {user_id: Money(amount, total.currency) 
                for user_id, amount in shares_minor.items()}
    
    @staticmethod
    def validate_split(total: Money, 
                      shares: Dict[int, Money]) -> bool:
        """
        Validate that a set of shares sums exactly to the total.
        """
        total_shares = sum(shares.values(), Money(0, total.currency))
        return total_shares.amount_minor == total.amount_minor


# Example usage
if __name__ == "__main__":
    from money import Money
    
    # Test equal split
    expense = Money(1000, "USD")  # $10.00
    participants = [1, 2, 3]
    shares = SplitEngine.split_equal(expense, participants)
    print(f"Equal split of $10.00: {shares}")
    print(f"Sum validation: {SplitEngine.validate_split(expense, shares)}")
    
    # Test percentage split
    weights = [(1, 5000), (2, 3000), (3, 2000)]  # 50/30/20
    shares_pct = SplitEngine.split_percentage(expense, weights)
    print(f"Percentage split: {shares_pct}")
    print(f"Sum validation: {SplitEngine.validate_split(expense, shares_pct)}")
    
    # Test custom split
    custom = [(1, 400), (2, 300), (3, 300)]
    shares_custom = SplitEngine.split_custom(expense, custom)
    print(f"Custom split: {shares_custom}")
    print(f"Sum validation: {SplitEngine.validate_split(expense, shares_custom)}")