//
//  Hand.swift
//  Blackjack
//
//  Represents a Blackjack hand with value calculation.
//

import Foundation
import CasinoKit

/// A hand of cards in Blackjack.
struct BlackjackHand: Identifiable, Equatable {
    let id = UUID()
    var cards: [Card]
    var bet: Int
    var isDoubledDown: Bool = false
    var isSplit: Bool = false
    var isStanding: Bool = false
    var result: HandResult?
    
    init(cards: [Card] = [], bet: Int = 0) {
        self.cards = cards
        self.bet = bet
    }
    
    /// The best possible value (highest without busting, or lowest if busted).
    var value: Int {
        let (hard, soft) = calculateValues()
        if soft <= 21 {
            return soft
        }
        return hard
    }
    
    /// Whether this hand has a soft value (usable ace).
    var isSoft: Bool {
        let (hard, soft) = calculateValues()
        return soft <= 21 && soft != hard
    }
    
    /// Whether the hand is over 21.
    var isBusted: Bool {
        value > 21
    }
    
    /// Whether this is a natural blackjack (two cards totaling 21).
    var isBlackjack: Bool {
        cards.count == 2 && value == 21 && !isSplit
    }
    
    /// Whether this hand has a splittable pair (two cards of same rank).
    /// Note: Additional conditions (balance, max splits, resplit aces) are checked by the engine.
    var canSplit: Bool {
        cards.count == 2 && cards[0].rank == cards[1].rank
    }
    
    /// Whether this hand has the card count to double down.
    /// Note: Additional conditions (balance, DAS rule) are checked by the engine.
    var canDoubleDown: Bool {
        cards.count == 2 && !isDoubledDown
    }
    
    /// Whether this hand can hit.
    /// Note: Standard Blackjack has NO card limit - you can hit until you bust or stand.
    var canHit: Bool {
        !isBusted && !isStanding && !isBlackjack
    }
    
    /// Calculates both hard and soft values.
    private func calculateValues() -> (hard: Int, soft: Int) {
        var hardValue = 0
        var aceCount = 0
        
        for card in cards {
            switch card.rank {
            case .ace:
                hardValue += 1
                aceCount += 1
            case .two: hardValue += 2
            case .three: hardValue += 3
            case .four: hardValue += 4
            case .five: hardValue += 5
            case .six: hardValue += 6
            case .seven: hardValue += 7
            case .eight: hardValue += 8
            case .nine: hardValue += 9
            case .ten, .jack, .queen, .king:
                hardValue += 10
            }
        }
        
        // Calculate soft value (one ace as 11)
        var softValue = hardValue
        if aceCount > 0 && hardValue + 10 <= 21 {
            softValue = hardValue + 10
        }
        
        return (hardValue, softValue)
    }
    
    /// Display string for the hand value.
    var valueDisplay: String {
        if isBlackjack {
            return "BJ"
        }
        let (hard, soft) = calculateValues()
        if isBusted {
            return "\(hard) 💥"
        }
        if isSoft && soft != hard {
            return "\(hard)/\(soft)"
        }
        return "\(value)"
    }
}

// MARK: - Card Value Extension

extension Card {
    /// The blackjack value of this card for display purposes (Ace = 11, face cards = 10).
    /// Note: Hand calculation handles ace flexibility (1 or 11).
    var blackjackValue: Int {
        switch rank {
        case .ace: return 11  // Show as 11 for display; hand calculation handles soft/hard
        case .two: return 2
        case .three: return 3
        case .four: return 4
        case .five: return 5
        case .six: return 6
        case .seven: return 7
        case .eight: return 8
        case .nine: return 9
        case .ten, .jack, .queen, .king: return 10
        }
    }
    
    /// The Hi-Lo card counting value.
    /// Low cards (2-6): +1 (good for player when removed)
    /// Neutral (7-9): 0
    /// High cards (10-A): -1 (bad for player when removed)
    var hiLoValue: Int {
        switch rank {
        case .two, .three, .four, .five, .six:
            return 1  // Low cards
        case .seven, .eight, .nine:
            return 0  // Neutral
        case .ten, .jack, .queen, .king, .ace:
            return -1 // High cards
        }
    }
    
    /// Display text for the Hi-Lo count value.
    var hiLoDisplayText: String {
        switch hiLoValue {
        case 1: return "+1"
        case -1: return "-1"
        default: return "0"
        }
    }
}

