import Foundation
import Observation

@Observable
final class GameState {
    var tableaus: [[Card]]
    var foundations: [[Card]]
    var stock: [Card]
    var waste: [Card]
    var freeCells: [Card?]

    var moves: Int = 0
    var score: Int = 0
    var phase: GamePhase = .notStarted

    private(set) var history: [GameSnapshot] = []
    private let maxHistorySize = 20

    var canUndo: Bool { !history.isEmpty }

    init() {
        self.tableaus = []
        self.foundations = []
        self.stock = []
        self.waste = []
        self.freeCells = []
    }

    func snapshot() -> GameSnapshot {
        GameSnapshot(
            tableaus: tableaus,
            foundations: foundations,
            stock: stock,
            waste: waste,
            freeCells: freeCells,
            moves: moves,
            score: score
        )
    }

    func restore(from snapshot: GameSnapshot) {
        tableaus = snapshot.tableaus
        foundations = snapshot.foundations
        stock = snapshot.stock
        waste = snapshot.waste
        freeCells = snapshot.freeCells
        moves = snapshot.moves
        score = snapshot.score
    }

    func pushHistory() {
        history.append(snapshot())
        if history.count > maxHistorySize {
            history.removeFirst()
        }
    }

    func popHistory() -> GameSnapshot? {
        history.popLast()
    }

    func clearHistory() {
        history.removeAll()
    }

    func reset(from snapshot: GameSnapshot, variant: GameVariant) {
        restore(from: snapshot)
        phase = .playing
        clearHistory()

        if variant.hasFreeCells {
            freeCells = Array(repeating: nil, count: variant.freeCellCount)
        } else {
            freeCells = []
        }
    }
}
