//
//  GameSettings.swift
//  Blackjack
//
//  User-configurable game settings including Blackjack rule variations.
//

import Foundation
import SwiftUI
import CasinoKit

/// Blackjack rule variation presets.
enum BlackjackStyle: String, CaseIterable, Identifiable {
    case vegas = "vegas"           // Vegas Strip rules
    case atlantic = "atlantic"     // Atlantic City rules
    case european = "european"     // European no-hole-card
    case custom = "custom"
    
    var id: String { rawValue }
    
    var displayName: String {
        switch self {
        case .vegas: return String(localized: "Vegas Strip")
        case .atlantic: return String(localized: "Atlantic City")
        case .european: return String(localized: "European")
        case .custom: return String(localized: "Custom")
        }
    }
    
    var description: String {
        switch self {
        case .vegas: return String(localized: "Dealer stands on soft 17, double after split, 3:2 blackjack")
        case .atlantic: return String(localized: "Dealer stands on soft 17, late surrender, 8 decks")
        case .european: return String(localized: "No hole card, dealer stands on soft 17, no surrender")
        case .custom: return String(localized: "Customize all rules")
        }
    }
}

/// Number of decks in the shoe.
enum DeckCount: Int, CaseIterable, Identifiable {
    case one = 1
    case two = 2
    case four = 4
    case six = 6
    case eight = 8
    
    var id: Int { rawValue }
    
    var displayName: String {
        switch self {
        case .one: return "1 Deck"
        case .two: return "2 Decks"
        case .four: return "4 Decks"
        case .six: return "6 Decks"
        case .eight: return "8 Decks"
        }
    }
    
    var description: String {
        switch self {
        case .one: return String(localized: "Single deck, higher variance")
        case .two: return String(localized: "Lower house edge")
        case .four: return String(localized: "Common shoe game")
        case .six: return String(localized: "Standard casino")
        case .eight: return String(localized: "Maximum penetration")
        }
    }
}

/// Observable settings class for Blackjack configuration.
@Observable
@MainActor
final class GameSettings {
    // MARK: - Game Style
    
    /// The preset rule variation.
    var gameStyle: BlackjackStyle = .vegas {
        didSet {
            applyStylePreset()
            save()
        }
    }
    
    // MARK: - Rule Options
    
    /// Number of decks in the shoe.
    var deckCount: DeckCount = .six { didSet { save() } }
    
    /// Whether dealer hits on soft 17.
    var dealerHitsSoft17: Bool = false { didSet { save() } }
    
    /// Whether player can double after split.
    var doubleAfterSplit: Bool = true { didSet { save() } }
    
    /// Whether player can re-split aces.
    var resplitAces: Bool = false { didSet { save() } }
    
    /// Whether late surrender is allowed.
    var lateSurrender: Bool = true { didSet { save() } }
    
    /// Whether European no-hole-card rule is used (dealer gets second card after player acts).
    var noHoleCard: Bool = false { didSet { save() } }
    
    /// Whether insurance is offered.
    var insuranceAllowed: Bool = true { didSet { save() } }
    
    /// Whether to skip the insurance prompt and auto-decline.
    var neverAskInsurance: Bool = false { didSet { save() } }
    
    /// Blackjack payout ratio (1.5 = 3:2, 1.2 = 6:5)
    var blackjackPayout: Double = 1.5 { didSet { save() } }
    
    // MARK: - Betting Limits
    
    /// The table limits preset.
    var tableLimits: TableLimits = .low { didSet { save() } }
    
    /// Minimum bet amount.
    var minBet: Int { tableLimits.minBet }
    
    /// Maximum bet amount.
    var maxBet: Int { tableLimits.maxBet }
    
    // MARK: - Starting Balance
    
    /// The starting balance for new games.
    var startingBalance: Int = 10_000 { didSet { save() } }
    
    // MARK: - Animation Settings
    
    /// Whether to show dealing animations.
    var showAnimations: Bool = true { didSet { save() } }
    
    /// Speed of card dealing (1.0 = normal)
    var dealingSpeed: Double = 1.0 { didSet { save() } }
    
    // MARK: - Side Bets
    
    /// Whether side bets (Perfect Pairs, 21+3) are enabled.
    var sideBetsEnabled: Bool = false { didSet { save() } }
    
    // MARK: - Display Settings
    
    /// Whether to show the cards remaining indicator.
    var showCardsRemaining: Bool = true { didSet { save() } }
    
    /// Whether to show hand history.
    var showHistory: Bool = true { didSet { save() } }
    
    /// Whether to show dealer hints (suggested action).
    var showHints: Bool = true { didSet { save() } }
    
    /// Whether to show the running card count (Hi-Lo system).
    var showCardCount: Bool = false { didSet { save() } }
    
    // MARK: - Sound Settings
    
    /// Whether sound effects are enabled.
    var soundEnabled: Bool = true { didSet { save() } }
    
    /// Whether haptic feedback is enabled.
    var hapticsEnabled: Bool = true { didSet { save() } }
    
    /// Volume level for sound effects.
    var soundVolume: Float = 1.0 { didSet { save() } }
    
    // MARK: - Initialization
    
    init() {
        self.persistence = CloudSyncManager<BlackjackSettingsData>()
        load()
        applyStylePreset()
    }
    
    // MARK: - Style Presets
    
    private func applyStylePreset() {
        guard gameStyle != .custom else { return }
        
        switch gameStyle {
        case .vegas:
            deckCount = .six
            dealerHitsSoft17 = false
            doubleAfterSplit = true
            resplitAces = false
            lateSurrender = false
            noHoleCard = false  // American: dealer gets hole card upfront
            blackjackPayout = 1.5
            
        case .atlantic:
            deckCount = .eight
            dealerHitsSoft17 = false
            doubleAfterSplit = true
            resplitAces = true
            lateSurrender = true
            noHoleCard = false  // American: dealer gets hole card upfront
            blackjackPayout = 1.5
            
        case .european:
            deckCount = .six
            dealerHitsSoft17 = false
            doubleAfterSplit = true
            resplitAces = false
            lateSurrender = false
            noHoleCard = true  // European: dealer gets second card after player acts
            blackjackPayout = 1.5
            
        case .custom:
            break
        }
    }
    
    // MARK: - Persistence
    
    private let persistence: CloudSyncManager<BlackjackSettingsData>
    
    var iCloudAvailable: Bool {
        FileManager.default.ubiquityIdentityToken != nil
    }
    
    func load() {
        let data = persistence.load()
        
        if let style = BlackjackStyle(rawValue: data.gameStyle) {
            self.gameStyle = style
        }
        if let count = DeckCount(rawValue: data.deckCount) {
            self.deckCount = count
        }
        if let limits = TableLimits(rawValue: data.tableLimits) {
            self.tableLimits = limits
        }
        
        self.startingBalance = data.startingBalance
        self.dealerHitsSoft17 = data.dealerHitsSoft17
        self.doubleAfterSplit = data.doubleAfterSplit
        self.resplitAces = data.resplitAces
        self.lateSurrender = data.lateSurrender
        self.noHoleCard = data.noHoleCard
        self.blackjackPayout = data.blackjackPayout
        self.insuranceAllowed = data.insuranceAllowed
        self.neverAskInsurance = data.neverAskInsurance
        self.sideBetsEnabled = data.sideBetsEnabled
        self.showAnimations = data.showAnimations
        self.dealingSpeed = data.dealingSpeed
        self.showCardsRemaining = data.showCardsRemaining
        self.showHistory = data.showHistory
        self.showHints = data.showHints
        self.showCardCount = data.showCardCount
        self.soundEnabled = data.soundEnabled
        self.hapticsEnabled = data.hapticsEnabled
        self.soundVolume = data.soundVolume
    }
    
    func save() {
        let data = BlackjackSettingsData(
            lastModified: Date(),
            gameStyle: gameStyle.rawValue,
            deckCount: deckCount.rawValue,
            tableLimits: tableLimits.rawValue,
            startingBalance: startingBalance,
            dealerHitsSoft17: dealerHitsSoft17,
            doubleAfterSplit: doubleAfterSplit,
            resplitAces: resplitAces,
            lateSurrender: lateSurrender,
            noHoleCard: noHoleCard,
            blackjackPayout: blackjackPayout,
            insuranceAllowed: insuranceAllowed,
            neverAskInsurance: neverAskInsurance,
            sideBetsEnabled: sideBetsEnabled,
            showAnimations: showAnimations,
            dealingSpeed: dealingSpeed,
            showCardsRemaining: showCardsRemaining,
            showHistory: showHistory,
            showHints: showHints,
            showCardCount: showCardCount,
            soundEnabled: soundEnabled,
            hapticsEnabled: hapticsEnabled,
            soundVolume: soundVolume
        )
        persistence.save(data)
    }
    
    /// Resets all settings to defaults.
    func resetToDefaults() {
        gameStyle = .vegas
        deckCount = .six
        tableLimits = .low
        startingBalance = 10_000
        dealerHitsSoft17 = false
        doubleAfterSplit = true
        resplitAces = false
        lateSurrender = true
        noHoleCard = false
        blackjackPayout = 1.5
        insuranceAllowed = true
        neverAskInsurance = false
        sideBetsEnabled = false
        showAnimations = true
        dealingSpeed = 1.0
        showCardsRemaining = true
        showHistory = true
        showHints = true
        showCardCount = false
        soundEnabled = true
        hapticsEnabled = true
        soundVolume = 1.0
        save()
    }
}

