from app.models import Event, EventType


class PointsService:
    """Service for calculating points and penalties"""

    STREAK_MULTIPLIERS = {
        0: 0.0,
        1: 0.0,
        2: 0.1,
        3: 0.2,
        4: 0.3,
    }
    MAX_STREAK_MULTIPLIER = 0.4

    # Drop penalty as percentage of challenge points
    DROP_PENALTY_PERCENTAGES = {
        0: 0.5,   # 1st drop: 50%
        1: 0.75,  # 2nd drop: 75%
    }
    MAX_DROP_PENALTY_PERCENTAGE = 1.0  # 3rd+ drop: 100%

    # Event point multipliers
    EVENT_MULTIPLIERS = {
        EventType.GOLDEN_HOUR.value: 1.5,
        EventType.DOUBLE_RISK.value: 0.5,
        EventType.JACKPOT.value: 3.0,
        # GAME_CHOICE uses 1.0 multiplier (default)
    }

    def calculate_completion_points(
        self,
        base_points: int,
        current_streak: int,
        event: Event | None = None,
    ) -> tuple[int, int, int]:
        """
        Calculate points earned for completing a challenge.

        Args:
            base_points: Base points for the challenge
            current_streak: Current streak before this completion
            event: Active event (optional)

        Returns:
            Tuple of (total_points, streak_bonus, event_bonus)
        """
        # Apply event multiplier first
        event_multiplier = 1.0
        if event:
            event_multiplier = self.EVENT_MULTIPLIERS.get(event.type, 1.0)

        adjusted_base = int(base_points * event_multiplier)
        event_bonus = adjusted_base - base_points

        # Then apply streak bonus
        streak_multiplier = self.STREAK_MULTIPLIERS.get(
            current_streak,
            self.MAX_STREAK_MULTIPLIER
        )
        streak_bonus = int(adjusted_base * streak_multiplier)

        total_points = adjusted_base + streak_bonus
        return total_points, streak_bonus, event_bonus

    def calculate_drop_penalty(
        self,
        consecutive_drops: int,
        challenge_points: int,
        event: Event | None = None
    ) -> int:
        """
        Calculate penalty for dropping a challenge.

        Args:
            consecutive_drops: Number of drops since last completion
            challenge_points: Base points of the challenge being dropped
            event: Active event (optional)

        Returns:
            Penalty points to subtract
        """
        # Double risk event = free drops
        if event and event.type == EventType.DOUBLE_RISK.value:
            return 0

        penalty_percentage = self.DROP_PENALTY_PERCENTAGES.get(
            consecutive_drops,
            self.MAX_DROP_PENALTY_PERCENTAGE
        )
        return int(challenge_points * penalty_percentage)

    def apply_event_multiplier(self, base_points: int, event: Event | None) -> int:
        """Apply event multiplier to points"""
        if not event:
            return base_points

        multiplier = self.EVENT_MULTIPLIERS.get(event.type, 1.0)
        return int(base_points * multiplier)
