//
//  CardsDisplayArea.swift
//  Baccarat
//
//  The cards display area showing both Player and Banker hands.
//  Animates from side-by-side (betting) to vertical stack (dealing).
//

import SwiftUI
import CasinoKit

/// The cards display area showing both hands.
/// - Betting phase: Horizontal side-by-side layout (Player | Banker)
/// - Dealing phase: Vertical stack with betted hand on bottom
struct CardsDisplayArea: View {
    let playerCards: [Card]
    let bankerCards: [Card]
    let playerCardsFaceUp: [Bool]
    let bankerCardsFaceUp: [Bool]
    let playerValue: Int
    let bankerValue: Int
    let playerIsWinner: Bool
    let bankerIsWinner: Bool
    let isTie: Bool
    let showAnimations: Bool
    let dealingSpeed: Double
    let revealStyle: RevealStyle
    let isWaitingForReveal: Bool
    let currentRevealIndex: Int
    let revealProgress: Double
    /// Which main bet is placed - nil if no main bet, true if Player, false if Banker.
    let bettedOnPlayer: Bool?
    /// Whether the game is in dealing/result phase (vertical layout) or betting phase (horizontal).
    let isDealing: Bool
    /// Full screen size for calculating card width in dealing mode.
    let screenSize: CGSize
    /// Total bet amount to display below the bottom hand during dealing.
    let totalBetAmount: Int
    let onReveal: () -> Void
    let onUpdateProgress: (Double) -> Void
    
    // MARK: - State
    
    @State private var containerWidth: CGFloat = 300
    @Namespace private var animation
    
    // MARK: - Environment
    
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    @Environment(\.verticalSizeClass) private var verticalSizeClass
    
    // MARK: - Computed Properties
    
    private var isLargeScreen: Bool {
        horizontalSizeClass == .regular
    }
    
    /// Whether we're in landscape mode
    private var isLandscape: Bool {
        verticalSizeClass == .compact || (isLargeScreen && screenSize.width > screenSize.height)
    }
    
    private var showDebugBorders: Bool { Design.showDebugBorders }
    
    // MARK: - Scaled Metrics (Dynamic Type)
    // These match Blackjack's HandLabelView for consistency
    
    @ScaledMetric(relativeTo: .headline) private var labelFontSize: CGFloat = Design.Size.handLabelFontSize
    @ScaledMetric(relativeTo: .headline) private var badgeHeight: CGFloat = CasinoDesign.Size.valueBadge
    @ScaledMetric(relativeTo: .caption) private var betFontSize: CGFloat = Design.Size.handNumberFontSize
    @ScaledMetric(relativeTo: .body) private var iconSize: CGFloat = Design.Size.handIconSize
    
    /// Whether Player hand should be on bottom in vertical mode.
    private var playerOnBottom: Bool {
        bettedOnPlayer ?? true
    }
    
    /// Spacing between hands
    private var handsSpacing: CGFloat {
        if isDealing {
            return isLargeScreen ? Design.Spacing.large : Design.Spacing.medium
        } else {
            return isLargeScreen ? Design.Spacing.xxxLarge : Design.Spacing.large
        }
    }
    
    // MARK: - Card Width Calculations
    
    /// Card section width for horizontal (betting) mode
    private var horizontalHandWidth: CGFloat {
        let spacing = isLargeScreen ? Design.Spacing.xxxLarge : Design.Spacing.large
        return max(100, (containerWidth - spacing) / 2)
    }
    
    /// Card section width for vertical (dealing) mode - matches Blackjack sizing
    /// Uses screen height as base (like Blackjack), which is smaller in landscape
    private var verticalHandWidth: CGFloat {
        // Use screen height (smaller dimension in landscape = smaller cards)
        let height = screenSize.height
        guard height > 100 else { return horizontalHandWidth }
        
        // Blackjack uses 0.18, but in landscape we may need slightly smaller
        let percentage: CGFloat = isLandscape ? 0.175 : height < 700 ? 0.14 : 0.18
        let cardWidth = height * percentage
        
        // CompactHandView uses: cardWidth = (containerWidth - 2 * spacing) / 3
        // So: containerWidth = 3 * cardWidth + 2 * spacing
        let spacing = Design.Spacing.medium
        let maxCards: CGFloat = 3
        return (cardWidth * maxCards) + (2 * spacing)
    }
    
    /// Current hand section width based on mode
    private var handSectionWidth: CGFloat {
        isDealing ? verticalHandWidth : horizontalHandWidth
    }
    
    // MARK: - Accessibility
    
    private var playerHandDescription: String {
        if playerCards.isEmpty {
            return String(localized: "No cards")
        }
        let visibleCards = zip(playerCards, playerCardsFaceUp)
            .filter { $1 }
            .map { "\($0.0.rank.accessibilityName) of \($0.0.suit.accessibilityName)" }
        
        if visibleCards.isEmpty {
            return String(localized: "Cards face down")
        }
        
        let format = String(localized: "handValueFormat")
        return visibleCards.joined(separator: ", ") + ". " + String(format: format, playerValue)
    }
    
    private var bankerHandDescription: String {
        if bankerCards.isEmpty {
            return String(localized: "No cards")
        }
        let visibleCards = zip(bankerCards, bankerCardsFaceUp)
            .filter { $1 }
            .map { "\($0.0.rank.accessibilityName) of \($0.0.suit.accessibilityName)" }
        
        if visibleCards.isEmpty {
            return String(localized: "Cards face down")
        }
        
        let format = String(localized: "handValueFormat")
        return visibleCards.joined(separator: ", ") + ". " + String(format: format, bankerValue)
    }
    
    // MARK: - Body
    
    var body: some View {
        // Use different layouts but keep view identity with matchedGeometryEffect
        Group {
            if isDealing {
                // Vertical layout with flexible spacing between hands
                VStack(spacing: 0) {
                    if playerOnBottom {
                        bankerHandSection(width: handSectionWidth)
                            .matchedGeometryEffect(id: "banker", in: animation)
                        
                        // Flexible spacer expands on taller screens
                        Spacer(minLength: handsSpacing)
                        
                        playerHandSection(width: handSectionWidth)
                            .matchedGeometryEffect(id: "player", in: animation)
                        
                        // Bet amount below the bottom hand
                        betAmountDisplay
                    } else {
                        playerHandSection(width: handSectionWidth)
                            .matchedGeometryEffect(id: "player", in: animation)
                        
                        // Flexible spacer expands on taller screens
                        Spacer(minLength: handsSpacing)
                        
                        bankerHandSection(width: handSectionWidth)
                            .matchedGeometryEffect(id: "banker", in: animation)
                        
                        // Bet amount below the bottom hand
                        betAmountDisplay
                    }
                }
            } else {
                // Horizontal layout - Player left, Banker right
                HStack(spacing: handsSpacing) {
                    playerHandSection(width: handSectionWidth)
                        .matchedGeometryEffect(id: "player", in: animation)
                    bankerHandSection(width: handSectionWidth)
                        .matchedGeometryEffect(id: "banker", in: animation)
                }
            }
        }
        .frame(maxWidth: .infinity)
        .padding(.top, Design.Spacing.medium)
        .padding(.bottom, Design.Spacing.large)
        .background(
            GeometryReader { geometry in
                Color.clear
                    .onAppear {
                        containerWidth = geometry.size.width * 0.95
                    }
                    .onChange(of: geometry.size.width) { _, newWidth in
                        containerWidth = newWidth * 0.95
                    }
            }
        )
        // Only show background in betting phase (horizontal layout)
        .background(
            Group {
                if !isDealing {
                    RoundedRectangle(cornerRadius: Design.CornerRadius.xLarge)
                        .fill(Color.black.opacity(Design.Opacity.quarter))
                        .accessibilityHidden(true)
                }
            }
        )
        .debugBorder(showDebugBorders, color: .mint, label: "HandsContainer")
        .animation(.easeOut(duration: 0.5), value: isDealing)
        .animation(.easeOut(duration: 0.4), value: playerOnBottom)
    }
    
    // MARK: - Private Views
    
    /// Bet amount display shown below the bottom hand during dealing.
    /// Matches Blackjack's PlayerHandView bet display styling.
    @ViewBuilder
    private var betAmountDisplay: some View {
        if totalBetAmount > 0 {
            HStack(spacing: Design.Spacing.xSmall) {
                Image(systemName: "dollarsign.circle.fill")
                    .font(.system(size: iconSize))
                    .foregroundStyle(.yellow)
                Text("\(totalBetAmount)")
                    .font(.system(size: betFontSize, weight: .bold, design: .rounded))
                    .foregroundStyle(.yellow)
            }
            .padding(.top, Design.Spacing.medium)
        }
    }
    
    private func playerHandSection(width: CGFloat) -> some View {
        // Calculate value from face-up cards
        let visibleValue: Int = {
            guard !playerCards.isEmpty else { return 0 }
            let faceUpCards = zip(playerCards, playerCardsFaceUp)
                .filter { $1 }
                .map { $0.0 }
            return faceUpCards.reduce(0) { $0 + $1.baccaratValue } % 10
        }()
        
        let allCardsFaceUp = !playerCards.isEmpty && playerCardsFaceUp.count == playerCards.count && playerCardsFaceUp.allSatisfy({ $0 })
        let _ = CasinoDesign.debugLog("🎯 Player: cards=\(playerCards.count), faceUp=\(playerCardsFaceUp.count), allFaceUp=\(allCardsFaceUp), visibleValue=\(visibleValue)")
        
        return VStack(spacing: Design.Spacing.small) {
            HStack(spacing: Design.Spacing.small) {
                Text("PLAYER")
                    .font(.system(size: labelFontSize, weight: .bold, design: .rounded))
                    .foregroundStyle(.white)
                
                // Always show value when there are cards - it updates as cards become visible
                if !playerCards.isEmpty {
                    HandValueBadge(value: visibleValue, color: .blue)
                        .animation(nil, value: visibleValue) // No animation when value changes
                }
            }
            .fixedSize() // Prevent the label from being constrained/truncated
            .frame(minHeight: badgeHeight)
            
            CompactHandView(
                cards: playerCards,
                cardsFaceUp: playerCardsFaceUp,
                isWinner: playerIsWinner,
                containerWidth: width,
                showAnimations: showAnimations,
                dealingSpeed: dealingSpeed,
                revealStyle: revealStyle,
                isWaitingForReveal: isWaitingForReveal,
                currentRevealIndex: currentRevealIndex,
                revealProgress: revealProgress,
                isPlayerHand: true,
                isBottom: playerOnBottom,
                isDealing: isDealing,
                onReveal: onReveal,
                onUpdateProgress: onUpdateProgress
            )
        }
        .frame(maxWidth: isDealing ? .infinity : width)
        .accessibilityElement(children: .ignore)
        .accessibilityLabel(String(localized: "Player hand"))
        .accessibilityValue(playerHandDescription + (playerIsWinner ? ", " + String(localized: "Winner") : ""))
    }
    
    private func bankerHandSection(width: CGFloat) -> some View {
        // Calculate value from face-up cards
        let visibleValue: Int = {
            guard !bankerCards.isEmpty else { return 0 }
            let faceUpCards = zip(bankerCards, bankerCardsFaceUp)
                .filter { $1 }
                .map { $0.0 }
            return faceUpCards.reduce(0) { $0 + $1.baccaratValue } % 10
        }()
        
        let allCardsFaceUp = !bankerCards.isEmpty && bankerCardsFaceUp.count == bankerCards.count && bankerCardsFaceUp.allSatisfy({ $0 })
        let _ = CasinoDesign.debugLog("🎯 Banker: cards=\(bankerCards.count), faceUp=\(bankerCardsFaceUp.count), allFaceUp=\(allCardsFaceUp), visibleValue=\(visibleValue)")
        
        return VStack(spacing: Design.Spacing.small) {
            HStack(spacing: Design.Spacing.small) {
                Text("BANKER")
                    .font(.system(size: labelFontSize, weight: .bold, design: .rounded))
                    .foregroundStyle(.white)
                
                // Always show value when there are cards - it updates as cards become visible
                if !bankerCards.isEmpty {
                    HandValueBadge(value: visibleValue, color: .red)
                        .animation(nil, value: visibleValue) // No animation when value changes
                }
            }
            .fixedSize() // Prevent the label from being constrained/truncated
            .frame(minHeight: badgeHeight)
            
            CompactHandView(
                cards: bankerCards,
                cardsFaceUp: bankerCardsFaceUp,
                isWinner: bankerIsWinner,
                containerWidth: width,
                showAnimations: showAnimations,
                dealingSpeed: dealingSpeed,
                revealStyle: revealStyle,
                isWaitingForReveal: isWaitingForReveal,
                currentRevealIndex: currentRevealIndex,
                revealProgress: revealProgress,
                isPlayerHand: false,
                isBottom: !playerOnBottom,
                isDealing: isDealing,
                onReveal: onReveal,
                onUpdateProgress: onUpdateProgress
            )
        }
        .frame(maxWidth: isDealing ? .infinity : width)
        .accessibilityElement(children: .ignore)
        .accessibilityLabel(String(localized: "Banker hand"))
        .accessibilityValue(bankerHandDescription + (bankerIsWinner ? ", " + String(localized: "Winner") : ""))
    }
}

// MARK: - Previews

#Preview("Horizontal - Betting Phase") {
    ZStack {
        TableBackgroundView()
        CardsDisplayArea(
            playerCards: [],
            bankerCards: [],
            playerCardsFaceUp: [],
            bankerCardsFaceUp: [],
            playerValue: 0,
            bankerValue: 0,
            playerIsWinner: false,
            bankerIsWinner: false,
            isTie: false,
            showAnimations: true,
            dealingSpeed: 1.0,
            revealStyle: .auto,
            isWaitingForReveal: false,
            currentRevealIndex: 0,
            revealProgress: 0,
            bettedOnPlayer: nil,
            isDealing: false,
            screenSize: CGSize(width: 400, height: 800),
            totalBetAmount: 0,
            onReveal: {},
            onUpdateProgress: { _ in }
        )
    }
}

#Preview("Vertical - Dealing (Bet on Player)") {
    ZStack {
        TableBackgroundView()
        CardsDisplayArea(
            playerCards: [
                Card(suit: .spades, rank: .king),
                Card(suit: .hearts, rank: .eight)
            ],
            bankerCards: [
                Card(suit: .clubs, rank: .seven),
                Card(suit: .diamonds, rank: .five)
            ],
            playerCardsFaceUp: [true, true],
            bankerCardsFaceUp: [true, true],
            playerValue: 8,
            bankerValue: 2,
            playerIsWinner: true,
            bankerIsWinner: false,
            isTie: false,
            showAnimations: true,
            dealingSpeed: 1.0,
            revealStyle: .auto,
            isWaitingForReveal: false,
            currentRevealIndex: 0,
            revealProgress: 0,
            bettedOnPlayer: true,
            isDealing: true,
            screenSize: CGSize(width: 400, height: 800),
            totalBetAmount: 150,
            onReveal: {},
            onUpdateProgress: { _ in }
        )
    }
}

#Preview("Vertical - Dealing (Bet on Banker)") {
    ZStack {
        TableBackgroundView()
        CardsDisplayArea(
            playerCards: [
                Card(suit: .spades, rank: .four),
                Card(suit: .hearts, rank: .three),
                Card(suit: .clubs, rank: .two)
            ],
            bankerCards: [
                Card(suit: .hearts, rank: .ace),
                Card(suit: .diamonds, rank: .ace),
                Card(suit: .spades, rank: .seven)
            ],
            playerCardsFaceUp: [true, true, true],
            bankerCardsFaceUp: [true, true, true],
            playerValue: 9,
            bankerValue: 9,
            playerIsWinner: false,
            bankerIsWinner: true,
            isTie: false,
            showAnimations: true,
            dealingSpeed: 1.0,
            revealStyle: .auto,
            isWaitingForReveal: false,
            currentRevealIndex: 0,
            revealProgress: 0,
            bettedOnPlayer: false,
            isDealing: true,
            screenSize: CGSize(width: 400, height: 800),
            totalBetAmount: 250,
            onReveal: {},
            onUpdateProgress: { _ in }
        )
    }
}
