//
//  BetType.swift
//  Baccarat
//
//  Bet types and payout rates for baccarat.
//

import Foundation
import SwiftUI

/// The types of bets available in baccarat.
enum BetType: String, CaseIterable, Identifiable {
    // MARK: - Main Bets
    case player = "Player"
    case banker = "Banker"
    case tie = "Tie"
    
    // MARK: - Side Bets
    case playerPair = "Player Pair"
    case bankerPair = "Banker Pair"
    case dragonBonusPlayer = "Dragon Bonus Player"
    case dragonBonusBanker = "Dragon Bonus Banker"
    
    var id: String { rawValue }
    
    /// Whether this is a main bet (Player/Banker) that is required to play.
    var isMainBet: Bool {
        self == .player || self == .banker
    }
    
    /// Whether this is a side bet.
    var isSideBet: Bool {
        !isMainBet && self != .tie
    }
    
    /// The base payout multiplier for winning this bet type.
    /// Note: Dragon Bonus has variable payouts based on margin - this is the natural win payout.
    var payoutMultiplier: Double {
        switch self {
        case .player: return 1.0
        case .banker: return 0.95  // 5% commission
        case .tie: return 8.0
        case .playerPair, .bankerPair: return 11.0  // 11:1
        case .dragonBonusPlayer, .dragonBonusBanker: return 1.0  // Base for natural
        }
    }
    
    /// Display name with payout info.
    var displayWithPayout: String {
        switch self {
        case .player: return "Player (1:1)"
        case .banker: return "Banker (0.95:1)"
        case .tie: return "Tie (8:1)"
        case .playerPair: return "P Pair (11:1)"
        case .bankerPair: return "B Pair (11:1)"
        case .dragonBonusPlayer: return "Dragon P"
        case .dragonBonusBanker: return "Dragon B"
        }
    }
    
    /// Short display name for betting zones.
    var shortName: String {
        switch self {
        case .player: return "PLAYER"
        case .banker: return "BANKER"
        case .tie: return "TIE"
        case .playerPair: return "P PAIR"
        case .bankerPair: return "B PAIR"
        case .dragonBonusPlayer: return "P BONUS"
        case .dragonBonusBanker: return "B BONUS"
        }
    }
    
    /// The payout description shown in betting zones.
    var payoutDescription: String {
        switch self {
        case .player: return "PAYS 1 TO 1"
        case .banker: return "PAYS 0.95 TO 1"
        case .tie: return "PAYS 8 TO 1"
        case .playerPair, .bankerPair: return "PAYS 11 TO 1"
        case .dragonBonusPlayer, .dragonBonusBanker: return "UP TO 30 TO 1"
        }
    }
    
    /// The color associated with this bet type.
    var color: Color {
        switch self {
        case .player: return .blue
        case .banker: return .red
        case .tie: return .green
        case .playerPair: return .blue.opacity(0.7)
        case .bankerPair: return .red.opacity(0.7)
        case .dragonBonusPlayer: return .purple
        case .dragonBonusBanker: return .orange
        }
    }
    
    /// All main betting options (required to play).
    static var mainBets: [BetType] {
        [.player, .banker]
    }
    
    /// All side bets.
    static var sideBets: [BetType] {
        [.tie, .playerPair, .bankerPair, .dragonBonusPlayer, .dragonBonusBanker]
    }
    
    /// Pair bets.
    static var pairBets: [BetType] {
        [.playerPair, .bankerPair]
    }
    
    /// Dragon bonus bets.
    static var dragonBets: [BetType] {
        [.dragonBonusPlayer, .dragonBonusBanker]
    }
}

/// Represents a bet placed by the user.
struct Bet: Identifiable, Equatable {
    let id = UUID()
    let type: BetType
    let amount: Int
    
    static func == (lhs: Bet, rhs: Bet) -> Bool {
        lhs.id == rhs.id
    }
}

/// Dragon Bonus payout table based on margin of victory.
enum DragonBonusPayout {
    /// Returns the payout multiplier for Dragon Bonus based on the margin of victory.
    /// Returns nil if the bet loses.
    static func multiplier(for margin: Int, isNatural: Bool) -> Int? {
        // Natural win (8 or 9)
        if isNatural && margin > 0 {
            return 1
        }
        
        // Non-natural wins by margin
        switch margin {
        case 9: return 30
        case 8: return 10
        case 7: return 6
        case 6: return 4
        case 5: return 2
        case 4: return 1
        default: return nil  // Loses on margin < 4, tie, or loss
        }
    }
    
    /// All possible payouts for display in rules.
    static var payoutTable: [(margin: String, payout: String)] {
        [
            ("Natural Win (8 or 9)", "1 to 1"),
            ("Win by 9", "30 to 1"),
            ("Win by 8", "10 to 1"),
            ("Win by 7", "6 to 1"),
            ("Win by 6", "4 to 1"),
            ("Win by 5", "2 to 1"),
            ("Win by 4", "1 to 1"),
            ("Win by 0-3 or Lose", "Lose")
        ]
    }
}
