# src/core/game_state.gd
class_name GameState
extends RefCounted

enum Phase { INIT, DEAL, TRIBUTE, PLAY, LEVEL_UP, GAME_OVER }

const _Actions = preload("res://src/core/actions.gd")

var phase: int = Phase.INIT
var round_seq: int = 0
var current_rank: int = 2
var rule_config: RuleConfig
var teams: Array = []
var player_hands: Array = [[], [], [], []]
var player_names: Array[String] = ["Player", "AI-1", "AI-2", "AI-3"]
var player_human: Array[bool] = [true, false, false, false]
var round: Round
var action_log: Array = []
var seed: int = 0
var finished_players: Array[int] = []
var current_winner_team: int = -1
var game_end_reason: String = ""

static func create(config: RuleConfig, seed_: int = -1) -> GameState:
    var gs := GameState.new()
    gs.rule_config = config
    if seed_ >= 0:
        gs.seed = seed_
    else:
        gs.seed = Time.get_unix_time_from_system() as int
    gs.teams = [_Actions.Team.create_team(0, 0, 2), _Actions.Team.create_team(1, 1, 3)]
    gs.round = Round.new()
    return gs

func get_team(player_idx: int) -> Actions.Team:
    for t in teams:
        if t.contains(player_idx):
            return t
    return null

func get_partner(player_idx: int) -> int:
    var t := get_team(player_idx)
    if t != null:
        return t.teammate_of(player_idx)
    return -1

func get_hand(player_idx: int) -> Array:
    return player_hands[player_idx]

func remove_cards_from_hand(player_idx: int, cards: Array) -> void:
    var hand: Array = player_hands[player_idx]
    var to_remove := {}
    for c in cards:
        to_remove[c.card_id] = true
    var new_hand: Array = []
    for c in hand:
        if not to_remove.has(c.card_id):
            new_hand.append(c)
    player_hands[player_idx] = new_hand

func add_cards_to_hand(player_idx: int, cards: Array) -> void:
    for c in cards:
        player_hands[player_idx].append(c)

func deal_cards(deck: Deck) -> void:
    for i in range(4):
        player_hands[i] = deck.deal(27)

func is_player_finished(player_idx: int) -> bool:
    return player_idx in finished_players

func add_finished_player(player_idx: int) -> void:
    if not is_player_finished(player_idx):
        finished_players.append(player_idx)

func get_rank_for_player(player_idx: int) -> int:
    var idx := finished_players.find(player_idx)
    if idx >= 0:
        return idx + 1
    return 0

func all_hands_empty() -> bool:
    var empty_count := 0
    for i in range(4):
        if player_hands[i].is_empty():
            empty_count += 1
    return empty_count >= 3

func to_packed_snapshot(for_player: int) -> Dictionary:
    return {
        "phase": phase,
        "current_rank": current_rank,
        "own_hand": _pack_hand(player_hands[for_player]),
        "table": _pack_table(round.table),
        "finished": finished_players.duplicate(),
        "team_scores": [teams[0].score, teams[1].score]
    }

func _pack_hand(hand: Array) -> Array:
    var result := []
    for c in hand:
        result.append(c.to_packed())
    return result

func _pack_table(table: Array) -> Array:
    var result := []
    for ep in table:
        var d := {"type": ep.type, "primary_rank": ep.primary_rank, "is_pure": ep.is_pure_bomb}
        var cards_packed := []
        for c in ep.cards:
            cards_packed.append(c.to_packed())
        d["cards"] = cards_packed
        result.append(d)
    return result
