//
//  GameTableView.swift
//  Baccarat
//
//  The main baccarat table view with all game elements.
//

import SwiftUI
import CasinoKit

/// The main game table view containing all game elements.
struct GameTableView: View, SherpaDelegate {
    @State private var settings = GameSettings()
    @State private var gameState: GameState?
    @State private var selectedChip: ChipDenomination = .hundred
    @State private var showSettings = false
    @State private var showRules = false
    @State private var showStats = false
    @State private var showWelcome = false
    
    // MARK: - Walkthrough State
    
    /// Whether the Sherpa walkthrough is active
    @State private var isWalkthroughActive = false
    
    /// Screen size for card sizing (measured from TableBackgroundView)
    @State private var screenSize: CGSize = CGSize(width: 375, height: 667)
    
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    @Environment(\.verticalSizeClass) private var verticalSizeClass
    
    // MARK: - Computed Properties
    
    /// Whether we're on iPad or large screen
    private var isLargeScreen: Bool {
        horizontalSizeClass == .regular
    }
    
    /// Whether we're in landscape mode (compact vertical on iPad)
    private var isLandscape: Bool {
        verticalSizeClass == .compact
    }
    
    /// Extra bottom padding for landscape mode where vertical space is tight
    private var bottomPadding: CGFloat {
        isLandscape ? Design.Spacing.medium : Design.Spacing.xSmall
    }
    
    /// Smaller spacer height - reduced in landscape
    private var smallSpacerHeight: CGFloat {
        isLandscape ? Design.Spacing.xxSmall : Design.Spacing.small
    }
    
    /// Maximum width for game content on large screens
    private var maxContentWidth: CGFloat {
        isLandscape ? CasinoDesign.Size.maxContentWidthLandscape : CasinoDesign.Size.maxContentWidthPortrait
    }
    
    /// Whether we're on a small screen (like iPhone SE) where space is tight
    private var isSmallScreen: Bool {
        screenSize.height < 700
    }
    
    private var state: GameState {
        gameState ?? GameState(settings: settings)
    }
    
    private var playerIsWinner: Bool {
        state.lastResult == .playerWins
    }
    
    private var bankerIsWinner: Bool {
        state.lastResult == .bankerWins
    }
    
    private var isTie: Bool {
        state.lastResult == .tie
    }
    
    /// Whether we're in a dealing/result phase (vertical layout) vs betting phase (horizontal)
    private var isDealing: Bool {
        state.currentPhase != .betting
    }
    
    // Use global debug flag from Design constants
    private var showDebugBorders: Bool { Design.showDebugBorders }
    
    /// Sherpa tags for the top bar elements
    private var topBarSherpaTags: TopBarSherpaTags<BaccaratWalkthroughTags> {
        TopBarSherpaTags(
            balance: .balance,
            cardsRemaining: .cardsRemaining,
            stats: .statsButton,
            rules: .rulesButton,
            settings: .settingsButton
        )
    }
    
    // MARK: - Body
    
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                // Table background - measures screen size for card sizing
                TableBackgroundView()
                    .onGeometryChange(for: CGSize.self) { proxy in
                        proxy.size
                    } action: { size in
                        screenSize = size
                    }
                
                // Main content
                mainContent(geometry: geometry)
                
                // Overlays
                overlays
            }
        }
        .onAppear {
            if gameState == nil {
                gameState = GameState(settings: settings)
            }
            checkForWelcomeSheet()
        }
        .sheet(isPresented: $showSettings) {
            if let state = gameState {
                SettingsView(settings: settings, gameState: state) {
                    gameState?.applySettings()
                }
            }
        }
        .onChange(of: showSettings) { wasShowing, isShowing in
            // When settings sheet dismisses, check if we should show welcome
            if wasShowing && !isShowing {
                checkForWelcomeSheet()
            }
        }
        .sheet(isPresented: $showRules) {
            RulesHelpView()
        }
        .sheet(isPresented: $showStats) {
            StatisticsSheetView(state: state)
        }
        .sheet(isPresented: $showWelcome) {
            WelcomeSheet(
                gameName: "Baccarat",
                gameEmoji: "🎴",
                features: [
                    WelcomeFeature(
                        icon: "hand.raised.fill",
                        title: String(localized: "Bet on Player, Banker, or Tie"),
                        description: String(localized: "The hand closest to 9 wins")
                    ),
                    WelcomeFeature(
                        icon: "chart.line.uptrend.xyaxis",
                        title: String(localized: "Track Patterns"),
                        description: String(localized: "Road maps show game history and trends")
                    ),
                    WelcomeFeature(
                        icon: "clock.badge.checkmark.fill",
                        title: String(localized: "Track Sessions"),
                        description: String(localized: "See detailed stats for each play session, just like at a real casino")
                    ),
                    WelcomeFeature(
                        icon: "gearshape.fill",
                        title: String(localized: "Customize Settings"),
                        description: String(localized: "Change table limits and display options")
                    )
                ],
                onboarding: state.onboarding,
                onDismiss: { showWelcome = false },
                onShowHints: startWalkthrough
            )
        }
        .onChange(of: showWelcome) { wasShowing, isShowing in
            // Handle swipe-down dismissal: treat as "Start Playing" (no walkthrough)
            if wasShowing && !isShowing && !state.onboarding.hasCompletedWelcome {
                state.onboarding.skipOnboarding()
            }
        }
        // Sherpa walkthrough modifier
        .sherpa(isActive: isWalkthroughActive, tags: BaccaratWalkthroughTags.self, delegate: self)
    }
    
    // MARK: - Onboarding Helpers
    
    private func checkForWelcomeSheet() {
        if !state.onboarding.hasCompletedWelcome {
            Task { @MainActor in
                try? await Task.sleep(for: .milliseconds(500))
                showWelcome = true
            }
        }
    }
    
    /// Starts the Sherpa walkthrough when user taps "Show Me How"
    private func startWalkthrough() {
        // Reset onboarding hints so walkthrough can be seen again
        state.onboarding.reset()
        state.onboarding.completeWelcome()
        isWalkthroughActive = true
    }
    
    // MARK: - SherpaDelegate
    
    /// Returns nil to hide skip button and progress indicator
    func accessoryView(sherpa: Sherpa) -> AnyView? {
        nil
    }
    
    func onWalkthroughComplete(sherpa: Sherpa) {
        isWalkthroughActive = false
        state.onboarding.completeWelcome()
    }
    
    func onWalkthroughSkipped(sherpa: Sherpa, atStep: Int, totalSteps: Int) {
        isWalkthroughActive = false
        state.onboarding.completeWelcome()
    }
    
    // MARK: - Private Views
    
    @ViewBuilder
    private func mainContent(geometry: GeometryProxy) -> some View {
        // Use geometry to detect landscape on iPad (width > height and large screen)
        let isLandscapeLayout = isLargeScreen && geometry.size.width > geometry.size.height
        
        if isLandscapeLayout {
            // Landscape iPad: RoadMap on left, game content on right
            landscapeLayout
        } else {
            // Portrait or iPhone: vertical stack with RoadMap inline
            portraitLayout
        }
    }
    
    /// Landscape layout with TopBar spanning full width, RoadMap grid on left below TopBar
    private var landscapeLayout: some View {
        VStack(spacing: 0) {
            // Top bar spans full width
            TopBarView(
                balance: state.balance,
                secondaryInfo: settings.showCardsRemaining ? "\(state.engine.shoe.cardsRemaining)" : nil,
                secondaryIcon: settings.showCardsRemaining ? "rectangle.portrait.on.rectangle.portrait.fill" : nil,
                onSettings: { showSettings = true },
                onHelp: { showRules = true },
                onStats: { showStats = true },
                sherpaTags: topBarSherpaTags
            )
            .debugBorder(showDebugBorders, color: .cyan, label: "TopBar")
            
            // Main content area with optional sidebar
            HStack(spacing: 0) {
                // Left side: Road map history grid
                if settings.showHistory {
                    VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
                        // Header with reading instructions
                        VStack(alignment: .leading, spacing: 5) {
                            Text("HISTORY")
                                .font(.system(size: Design.BaseFontSize.xLarge, weight: .bold, design: .rounded))
                                .foregroundStyle(.white.opacity(Design.Opacity.strong))
                            
                            Text("↓ then →")
                                .font(.system(size: Design.BaseFontSize.large, design: .rounded))
                                .foregroundStyle(.white.opacity(Design.Opacity.medium))
                        }
                        .padding(.leading, Design.Spacing.small)
                        .padding(.horizontal, Design.Spacing.small)
                        .padding(.top, Design.Spacing.small)
                        
                        // Grid-based road map (rows calculated dynamically)
                        RoadMapGridView(
                            results: state.recentResults,
                            dotSize: 32
                        )
                        .frame(maxHeight: .infinity)
                        
                        Spacer(minLength: 0)
                    }
                    .sherpaTag(BaccaratWalkthroughTags.history)
                    .frame(width: 240)
                    .background(
                        RoundedRectangle(cornerRadius: Design.CornerRadius.medium)
                            .fill(Color.black.opacity(Design.Opacity.light))
                            .padding(Design.Spacing.xSmall)
                    )
                    .padding(.leading, Design.Spacing.medium)
                    .debugBorder(showDebugBorders, color: .orange, label: "RoadMap")
                }
                
                // Right side: Main game content
                VStack(spacing: 0) {
                    Spacer(minLength: 0)
                    
                    // Cards display area
                    CardsDisplayArea(
                        playerCards: state.visiblePlayerCards,
                        bankerCards: state.visibleBankerCards,
                        playerCardsFaceUp: state.playerCardsFaceUp,
                        bankerCardsFaceUp: state.bankerCardsFaceUp,
                        playerValue: state.playerHandValue,
                        bankerValue: state.bankerHandValue,
                        playerIsWinner: playerIsWinner,
                        bankerIsWinner: bankerIsWinner,
                        isTie: isTie,
                        showAnimations: settings.showAnimations,
                        dealingSpeed: settings.dealingSpeed,
                        bettedOnPlayer: state.bettedOnPlayer,
                        isDealing: isDealing,
                        screenSize: screenSize
                    )
                    .frame(maxWidth: maxContentWidth)
                    .padding(.horizontal, Design.Spacing.medium)
                    .debugBorder(showDebugBorders, color: .red, label: "CardsArea")
                    
                    Spacer(minLength: 0)
                    
                    // Betting table
                    BettingTableView(
                        gameState: state,
                        selectedChip: selectedChip
                    )
                    .frame(maxWidth: maxContentWidth)
                    .padding(.horizontal, Design.Spacing.medium)
                    .debugBorder(showDebugBorders, color: .blue, label: "BetTable")
                    
                    // Betting hint (static, below table, above chips)
                    if let hintInfo = state.currentHintInfo {
                        BettingHintView(
                            hint: hintInfo.text,
                            secondaryInfo: hintInfo.secondaryText,
                            style: hintInfo.style
                        )
                        .transition(.opacity)
                        .padding(.vertical, Design.Spacing.small)
                        .debugBorder(showDebugBorders, color: .purple, label: "Hint")
                    }
                    
                    Spacer(minLength: Design.Spacing.xSmall)
                    
                    // Chip selector - only shown during betting phase
                    if state.currentPhase == .betting && !state.showResultBanner {
                        ChipSelectorView(
                            selectedChip: $selectedChip,
                            balance: state.balance,
                            currentBet: state.minBetForChipSelector,
                            maxBet: state.maxBet
                        )
                        .sherpaTag(BaccaratWalkthroughTags.chipSelector)
                        .transition(.opacity.combined(with: .move(edge: .bottom)))
                        .debugBorder(showDebugBorders, color: .pink, label: "ChipSelector")
                    }
                    
                    Spacer(minLength: Design.Spacing.xSmall)
                    
                    // Action buttons - hidden on small screens during dealing to save space
                    if !isDealing {
                        // Action buttons
                        ActionButtonsView(
                            gameState: state,
                            onDeal: {
                                Task {
                                    await state.deal()
                                }
                            },
                            onClear: { state.clearBets() },
                            onNewRound: { state.newRound() }
                        )
                        .frame(maxWidth: maxContentWidth * 0.8)
                        .padding(.horizontal)
                        .padding(.bottom, Design.Spacing.small)
                        .debugBorder(showDebugBorders, color: .green, label: "ActionBtns")
                    }
                }
                .frame(maxWidth: .infinity)
                .animation(.easeInOut(duration: Design.Animation.quick), value: state.currentPhase)
                .debugBorder(showDebugBorders, color: .white, label: "GameContent")
            }
        }
        .safeAreaPadding(.bottom, Design.Spacing.small)
    }
    
    /// Portrait layout - vertical card layout, no RoadMap (shown only in landscape)
    private var portraitLayout: some View {
        VStack(spacing: 0) {
            // Top bar with balance and info (from CasinoKit)
            TopBarView(
                balance: state.balance,
                secondaryInfo: settings.showCardsRemaining ? "\(state.engine.shoe.cardsRemaining)" : nil,
                secondaryIcon: settings.showCardsRemaining ? "rectangle.portrait.on.rectangle.portrait.fill" : nil,
                onSettings: { showSettings = true },
                onHelp: { showRules = true },
                onStats: { showStats = true },
                sherpaTags: topBarSherpaTags
            )
            .debugBorder(showDebugBorders, color: .cyan, label: "TopBar")
                        
            // Cards display area - animates from horizontal to vertical when dealing
            CardsDisplayArea(
                playerCards: state.visiblePlayerCards,
                bankerCards: state.visibleBankerCards,
                playerCardsFaceUp: state.playerCardsFaceUp,
                bankerCardsFaceUp: state.bankerCardsFaceUp,
                playerValue: state.playerHandValue,
                bankerValue: state.bankerHandValue,
                playerIsWinner: playerIsWinner,
                bankerIsWinner: bankerIsWinner,
                isTie: isTie,
                showAnimations: settings.showAnimations,
                dealingSpeed: settings.dealingSpeed,
                bettedOnPlayer: state.bettedOnPlayer,
                isDealing: isDealing,
                screenSize: screenSize
            )
            .frame(maxWidth: isLargeScreen ? maxContentWidth : .infinity)
            .padding(.horizontal, Design.Spacing.medium)
            .debugBorder(showDebugBorders, color: .red, label: "CardsArea")
            
            Spacer(minLength: smallSpacerHeight)
                .debugBorder(showDebugBorders, color: .yellow, label: "Spacer2")
            
            // Road map history - show in portrait before deal on larger screens
            if settings.showHistory && !isSmallScreen && !isDealing {
                RoadMapView(results: state.recentResults)
                    .sherpaTag(BaccaratWalkthroughTags.history)
                    .frame(maxWidth: isLargeScreen ? maxContentWidth : .infinity)
                    .padding(.horizontal, Design.Spacing.medium)
                    .debugBorder(showDebugBorders, color: .orange, label: "RoadMap")
                
                Spacer(minLength: smallSpacerHeight)
                    .debugBorder(showDebugBorders, color: .yellow, label: "Spacer3")
            }
            
            // Betting table
            BettingTableView(
                gameState: state,
                selectedChip: selectedChip
            )
            .frame(maxWidth: isLargeScreen ? maxContentWidth : .infinity)
            .padding(.horizontal, Design.Spacing.medium)
            .debugBorder(showDebugBorders, color: .blue, label: "BetTable")
            
            // Betting hint (static, below table, above chips)
            if let hintInfo = state.currentHintInfo {
                BettingHintView(
                    hint: hintInfo.text,
                    secondaryInfo: hintInfo.secondaryText,
                    style: hintInfo.style
                )
                .transition(.opacity)
                .padding(.vertical, Design.Spacing.small)
                .debugBorder(showDebugBorders, color: .purple, label: "Hint")
            }
            
            // Chip selector - only shown during betting phase
            if state.currentPhase == .betting && !state.showResultBanner {
                ChipSelectorView(
                    selectedChip: $selectedChip,
                    balance: state.balance,
                    currentBet: state.minBetForChipSelector,
                    maxBet: state.maxBet
                )
                .sherpaTag(BaccaratWalkthroughTags.chipSelector)
                .transition(.opacity.combined(with: .move(edge: .bottom)))
                .debugBorder(showDebugBorders, color: .pink, label: "ChipSelector")
            }
                        
            // Action buttons - hidden on small screens during dealing to save space
            if isSmallScreen && isDealing {
                Spacer()
                    .frame(height: 5)
            } else {
                ActionButtonsView(
                    gameState: state,
                    onDeal: {
                        Task {
                            await state.deal()
                        }
                    },
                    onClear: { state.clearBets() },
                    onNewRound: { state.newRound() }
                )
                .frame(maxWidth: isLargeScreen ? maxContentWidth * 0.8 : .infinity)
                .padding(.horizontal)
                .padding(.bottom, bottomPadding)
                .debugBorder(showDebugBorders, color: .green, label: "ActionBtns")
            }
        }
        .animation(.easeInOut(duration: Design.Animation.quick), value: state.currentPhase)
        .safeAreaPadding(.bottom)
        .debugBorder(showDebugBorders, color: .white, label: "MainContent")
    }
    
    @ViewBuilder
    private var overlays: some View {
        // Result banner overlay
        if state.showResultBanner, let result = state.lastResult {
            ResultBannerView(
                result: result,
                totalWinnings: state.lastWinnings,
                betResults: state.betResults,
                playerHadPair: state.playerHadPair,
                bankerHadPair: state.bankerHadPair,
                currentBalance: state.balance,
                minBet: state.minBet,
                onNewRound: { state.newRound() },
                onGameOver: {
                    state.resetGame()
                }
            )
            .transition(.opacity)
            
            // Confetti for wins (from CasinoKit)
            if state.lastWinnings > 0 {
                ConfettiView()
            }
        }
        
        // Game Over overlay
        if state.balance == 0 && state.currentBets.isEmpty && !state.isAnimating {
            GameOverView(
                roundsPlayed: state.roundHistory.count,
                onPlayAgain: { state.resetGame() }
            )
            .transition(.opacity)
        }
    }
}

// MARK: - Previews

#Preview("Game Table") {
    GameTableView()
}
