//
//  RoadMapBuilder.swift
//  Baccarat
//
//  Builds road map data structures from round results.
//  Implements Big Road layout and derived road algorithms (Big Eye Boy, Small Road, Cockroach Pig).
//

import Foundation

// MARK: - Road Map Builder

/// Builds road map data from round results.
/// Converts raw round history into structured Big Road and derived road entries.
enum RoadMapBuilder {
    
    /// Maximum number of rows before dragon tail wrapping.
    static let maxRows = 6
    
    // MARK: - Big Road
    
    /// Builds Big Road entries from round results.
    /// - Parameter results: The round history to convert.
    /// - Returns: An array of BigRoadEntry positioned in the grid.
    static func buildBigRoad(from results: [RoundResult]) -> [BigRoadEntry] {
        guard !results.isEmpty else { return [] }
        
        var entries: [BigRoadEntry] = []
        var currentColumn = 0
        var currentRow = 0
        var lastNonTieResult: GameResult?
        var pendingTies = 0
        
        for result in results {
            if result.result == .tie {
                // Ties don't create new entries - they attach to the previous result
                pendingTies += 1
                
                // If we have entries, update the last one with the tie count
                if !entries.isEmpty {
                    let lastIndex = entries.count - 1
                    let lastEntry = entries[lastIndex]
                    entries[lastIndex] = BigRoadEntry(
                        id: lastEntry.id,
                        result: lastEntry.result,
                        column: lastEntry.column,
                        row: lastEntry.row,
                        tieCount: lastEntry.tieCount + 1,
                        isNatural: lastEntry.isNatural,
                        hasPair: lastEntry.hasPair,
                        roundResult: lastEntry.roundResult
                    )
                }
                continue
            }
            
            // Determine if we need a new column
            if let lastResult = lastNonTieResult {
                if result.result != lastResult {
                    // Winner changed - start new column
                    currentColumn += 1
                    currentRow = 0
                } else {
                    // Same winner - continue down the column
                    currentRow += 1
                    
                    // Handle dragon tail (wrap to next column if exceeding max rows)
                    if currentRow >= maxRows {
                        currentColumn += 1
                        currentRow = maxRows - 1
                    }
                }
            }
            
            let entry = BigRoadEntry(
                result: result.result,
                column: currentColumn,
                row: currentRow,
                tieCount: 0,
                isNatural: result.isNatural,
                hasPair: result.hasPair,
                roundResult: result
            )
            
            entries.append(entry)
            lastNonTieResult = result.result
            pendingTies = 0
        }
        
        return entries
    }
    
    /// Builds Big Road columns from entries for easier pattern analysis.
    /// - Parameter entries: The Big Road entries.
    /// - Returns: An array of BigRoadColumn containing grouped entries.
    static func buildBigRoadColumns(from entries: [BigRoadEntry]) -> [BigRoadColumn] {
        guard !entries.isEmpty else { return [] }
        
        var columns: [BigRoadColumn] = []
        var currentColumnIndex = -1
        
        for entry in entries {
            if entry.column > currentColumnIndex {
                // Start new column(s) - handle gaps from dragon tail
                while columns.count <= entry.column {
                    columns.append(BigRoadColumn(index: columns.count))
                }
                currentColumnIndex = entry.column
            }
            
            if entry.column < columns.count {
                columns[entry.column].entries.append(entry)
            }
        }
        
        return columns
    }
    
    // MARK: - Derived Roads
    
    /// Builds a derived road (Big Eye Boy, Small Road, or Cockroach Pig) from Big Road columns.
    /// - Parameters:
    ///   - columns: The Big Road columns to analyze.
    ///   - roadType: The type of derived road to build.
    /// - Returns: An array of DerivedRoadEntry for the specified road type.
    static func buildDerivedRoad(
        from columns: [BigRoadColumn],
        roadType: RoadType
    ) -> [DerivedRoadEntry] {
        guard roadType.isDerived else { return [] }
        
        let offset = roadType.columnOffset
        let startingColumn = roadType.startingColumn
        
        guard columns.count >= startingColumn else { return [] }
        
        var entries: [DerivedRoadEntry] = []
        var derivedColumn = 0
        var derivedRow = 0
        
        // Process each column starting from the required starting column
        for columnIndex in (startingColumn - 1)..<columns.count {
            let column = columns[columnIndex]
            
            // Process each entry in the column
            for (entryIndex, _) in column.entries.enumerated() {
                let isRed: Bool
                
                if entryIndex == 0 {
                    // First entry in column - compare column depths
                    isRed = compareColumnDepths(
                        columns: columns,
                        currentColumn: columnIndex,
                        offset: offset
                    )
                    
                    // New column in derived road
                    if !entries.isEmpty {
                        derivedColumn += 1
                        derivedRow = 0
                    }
                } else {
                    // Continuation entry - compare cells
                    isRed = compareCells(
                        columns: columns,
                        currentColumn: columnIndex,
                        currentRow: entryIndex,
                        offset: offset
                    )
                    
                    derivedRow += 1
                    
                    // Handle wrapping in derived road
                    if derivedRow >= maxRows {
                        derivedColumn += 1
                        derivedRow = maxRows - 1
                    }
                }
                
                let entry = DerivedRoadEntry(
                    isRed: isRed,
                    column: derivedColumn,
                    row: derivedRow
                )
                entries.append(entry)
            }
        }
        
        return entries
    }
    
    // MARK: - Private Helpers
    
    /// Compares column depths for the first entry in a new Big Road column.
    /// Used by derived roads to determine if patterns are repeating.
    /// - Parameters:
    ///   - columns: All Big Road columns.
    ///   - currentColumn: The current column index being analyzed.
    ///   - offset: The column offset (1 for Big Eye Boy, 2 for Small Road, 3 for Cockroach Pig).
    /// - Returns: `true` (red) if depths match, `false` (blue) if they differ.
    private static func compareColumnDepths(
        columns: [BigRoadColumn],
        currentColumn: Int,
        offset: Int
    ) -> Bool {
        let previousColumn = currentColumn - 1
        let compareColumn = currentColumn - 1 - offset
        
        guard previousColumn >= 0, compareColumn >= 0 else {
            return false // Not enough history - default to blue
        }
        
        guard previousColumn < columns.count, compareColumn < columns.count else {
            return false
        }
        
        let previousDepth = columns[previousColumn].depth
        let compareDepth = columns[compareColumn].depth
        
        return previousDepth == compareDepth
    }
    
    /// Compares cells for continuation entries in a Big Road column.
    /// Looks at the cell one column left and the cell above that.
    /// - Parameters:
    ///   - columns: All Big Road columns.
    ///   - currentColumn: The current column index.
    ///   - currentRow: The current row index.
    ///   - offset: The column offset for the derived road type.
    /// - Returns: `true` (red) if cells match or both empty, `false` (blue) if they differ.
    private static func compareCells(
        columns: [BigRoadColumn],
        currentColumn: Int,
        currentRow: Int,
        offset: Int
    ) -> Bool {
        let lookbackColumn = currentColumn - offset
        let lookbackRow = currentRow - 1
        
        guard lookbackColumn >= 0, lookbackRow >= 0 else {
            return false // Not enough history - default to blue
        }
        
        guard lookbackColumn < columns.count else {
            return false
        }
        
        let lookbackColumnData = columns[lookbackColumn]
        
        // Check if cell at (lookbackColumn, currentRow-1) exists
        let cellExists = lookbackRow < lookbackColumnData.depth
        
        // Check if cell at (lookbackColumn, currentRow) exists
        let cellBelowExists = currentRow < lookbackColumnData.depth
        
        // If both exist or both don't exist, return red (pattern)
        // If one exists and one doesn't, return blue (break)
        return cellExists == cellBelowExists
    }
    
    // MARK: - Convenience
    
    /// Builds all road maps from round results.
    /// - Parameter results: The round history.
    /// - Returns: A tuple containing Big Road entries and all derived road entries.
    static func buildAllRoads(from results: [RoundResult]) -> (
        bigRoad: [BigRoadEntry],
        bigEyeBoy: [DerivedRoadEntry],
        smallRoad: [DerivedRoadEntry],
        cockroachPig: [DerivedRoadEntry]
    ) {
        let bigRoad = buildBigRoad(from: results)
        let columns = buildBigRoadColumns(from: bigRoad)
        
        return (
            bigRoad: bigRoad,
            bigEyeBoy: buildDerivedRoad(from: columns, roadType: .bigEyeBoy),
            smallRoad: buildDerivedRoad(from: columns, roadType: .smallRoad),
            cockroachPig: buildDerivedRoad(from: columns, roadType: .cockroachPig)
        )
    }
}
