class_name GameState
extends RefCounted

## GameState - Central game state container and rules engine

signal game_started
signal game_ended(winner_index: int)
signal card_played(card: CardInstance, player_index: int)
signal card_moved(card: CardInstance, from_zone: Enums.ZoneType, to_zone: Enums.ZoneType)
signal damage_dealt(player_index: int, amount: int, cards: Array[CardInstance])
signal forward_broken(card: CardInstance)
signal attack_declared(attacker: CardInstance)
signal block_declared(blocker: CardInstance)
signal combat_resolved(attacker: CardInstance, blocker: CardInstance)
signal cp_generated(player_index: int, element: Enums.Element, amount: int)

# Players
var players: Array[Player] = []

# Turn management
var turn_manager: TurnManager

# Shared stack for abilities/summons
var stack: Zone

# Game state flags
var game_active: bool = false
var winner_index: int = -1

func _init() -> void:
	turn_manager = TurnManager.new()
	stack = Zone.new(Enums.ZoneType.STACK, -1)

	# Connect turn manager signals
	turn_manager.phase_changed.connect(_on_phase_changed)
	turn_manager.turn_started.connect(_on_turn_started)
	turn_manager.turn_ended.connect(_on_turn_ended)

## Initialize a new game with two players
func setup_game(deck1: Array[String], deck2: Array[String]) -> void:
	# Create players
	players.clear()
	players.append(Player.new(0, "Player 1"))
	players.append(Player.new(1, "Player 2"))

	# Setup decks
	players[0].setup_deck(deck1)
	players[1].setup_deck(deck2)

	game_active = false
	winner_index = -1

## Start the game
func start_game(first_player: int = -1) -> void:
	if first_player < 0:
		first_player = randi() % 2

	players[first_player].is_first_player = true

	# Draw initial hands (5 cards each)
	players[0].draw_cards(5)
	players[1].draw_cards(5)

	game_active = true
	turn_manager.start_game(first_player)

	game_started.emit()

## Get current player
func get_current_player() -> Player:
	return players[turn_manager.current_player_index]

## Get opponent of current player
func get_opponent() -> Player:
	return players[1 - turn_manager.current_player_index]

## Get player by index
func get_player(index: int) -> Player:
	if index >= 0 and index < players.size():
		return players[index]
	return null

## Execute Active Phase
func execute_active_phase() -> void:
	var player = get_current_player()
	player.activate_all()
	turn_manager.advance_phase()

## Execute Draw Phase
func execute_draw_phase() -> void:
	var player = get_current_player()
	var draw_count = turn_manager.get_draw_count()

	var drawn = player.draw_cards(draw_count)

	# Check for loss condition (can't draw)
	if drawn.size() < draw_count and player.deck.is_empty():
		_check_loss_conditions()

	turn_manager.advance_phase()

## End Main Phase
func end_main_phase() -> void:
	# Clear any unused CP
	get_current_player().cp_pool.clear()
	turn_manager.advance_phase()

## Play a card from hand
func play_card(player_index: int, card: CardInstance) -> bool:
	if not game_active:
		return false

	if player_index != turn_manager.current_player_index:
		return false

	if not turn_manager.is_main_phase():
		return false

	var player = players[player_index]

	# Validate and play
	if player.play_card(card):
		card_played.emit(card, player_index)
		card_moved.emit(card, Enums.ZoneType.HAND,
			Enums.ZoneType.FIELD_FORWARDS if card.is_forward() else Enums.ZoneType.FIELD_BACKUPS)
		return true

	return false

## Discard a card for CP
func discard_for_cp(player_index: int, card: CardInstance) -> bool:
	if not game_active:
		return false

	var player = players[player_index]
	var element = card.get_element()

	if player.discard_for_cp(card):
		cp_generated.emit(player_index, element, 2)
		card_moved.emit(card, Enums.ZoneType.HAND, Enums.ZoneType.BREAK)
		return true

	return false

## Dull a backup for CP
func dull_backup_for_cp(player_index: int, card: CardInstance) -> bool:
	if not game_active:
		return false

	var player = players[player_index]
	var element = card.get_element()

	if player.dull_backup_for_cp(card):
		cp_generated.emit(player_index, element, 1)
		return true

	return false

## Start Attack Phase
func start_attack_phase() -> void:
	turn_manager.start_attack_declaration()

## Declare an attack
func declare_attack(attacker: CardInstance) -> bool:
	if not game_active:
		return false

	if not turn_manager.is_attack_phase():
		return false

	var player = get_current_player()

	if not player.field_forwards.has_card(attacker):
		return false

	if not attacker.can_attack():
		return false

	# Dull the attacker (unless Brave)
	if not attacker.has_brave():
		attacker.dull()

	attacker.attacked_this_turn = true
	turn_manager.set_attacker(attacker)

	attack_declared.emit(attacker)
	return true

## Declare a block
func declare_block(blocker: CardInstance) -> bool:
	if not game_active:
		return false

	if turn_manager.attack_step != Enums.AttackStep.BLOCK_DECLARATION:
		return false

	var opponent = get_opponent()

	if blocker != null:
		if not opponent.field_forwards.has_card(blocker):
			return false

		if not blocker.can_block():
			return false

	turn_manager.set_blocker(blocker)
	if blocker:
		block_declared.emit(blocker)

	return true

## Skip blocking
func skip_block() -> bool:
	return declare_block(null)

## Resolve combat damage
func resolve_combat() -> void:
	if turn_manager.attack_step != Enums.AttackStep.DAMAGE_RESOLUTION:
		return

	var attacker = turn_manager.current_attacker
	var blocker = turn_manager.current_blocker

	if blocker == null:
		# Unblocked - deal 1 damage to opponent
		_deal_damage_to_player(1 - turn_manager.current_player_index, 1)
	else:
		# Blocked - exchange damage
		var attacker_power = attacker.get_power()
		var blocker_power = blocker.get_power()

		# Apply damage
		var attacker_broken = attacker.apply_damage(blocker_power)
		var blocker_broken = blocker.apply_damage(attacker_power)

		# Break destroyed forwards
		if attacker_broken:
			_break_forward(attacker, turn_manager.current_player_index)

		if blocker_broken:
			_break_forward(blocker, 1 - turn_manager.current_player_index)

	combat_resolved.emit(attacker, blocker)
	turn_manager.complete_attack()

## End Attack Phase (no more attacks)
func end_attack_phase() -> void:
	turn_manager.end_attack_phase()

## Execute End Phase
func execute_end_phase() -> void:
	var player = get_current_player()

	# Discard to hand limit
	var discarded = player.discard_to_hand_limit()
	for card in discarded:
		card_moved.emit(card, Enums.ZoneType.HAND, Enums.ZoneType.BREAK)

	# Cleanup
	player.end_turn_cleanup()

	turn_manager.advance_phase()

## Deal damage to a player
func _deal_damage_to_player(player_index: int, amount: int) -> void:
	var player = players[player_index]
	var damage_cards = player.take_damage(amount)

	damage_dealt.emit(player_index, amount, damage_cards)

	# Check for EX Bursts (simplified - would need full implementation)
	for card in damage_cards:
		if card.card_data and card.card_data.has_ex_burst:
			# TODO: Offer EX Burst choice to player
			pass

	_check_loss_conditions()

## Break a forward
func _break_forward(card: CardInstance, player_index: int) -> void:
	var player = players[player_index]
	if player.break_card(card):
		forward_broken.emit(card)
		card_moved.emit(card, Enums.ZoneType.FIELD_FORWARDS, Enums.ZoneType.BREAK)

## Check for game-ending conditions
func _check_loss_conditions() -> void:
	for i in range(players.size()):
		var player = players[i]

		# Check damage
		if player.has_lost():
			_end_game(1 - i)  # Other player wins
			return

		# Check deck out (can't draw when needed)
		# This is checked during draw phase

## End the game
func _end_game(winner: int) -> void:
	game_active = false
	winner_index = winner
	game_ended.emit(winner)

## Phase change handler
func _on_phase_changed(phase: Enums.TurnPhase) -> void:
	match phase:
		Enums.TurnPhase.ACTIVE:
			execute_active_phase()
		Enums.TurnPhase.DRAW:
			execute_draw_phase()
		Enums.TurnPhase.ATTACK:
			start_attack_phase()
		Enums.TurnPhase.END:
			execute_end_phase()

## Turn started handler
func _on_turn_started(player_index: int, _turn_number: int) -> void:
	players[player_index].start_turn()

## Turn ended handler
func _on_turn_ended(_player_index: int) -> void:
	pass

func _to_string() -> String:
	if not game_active:
		return "[GameState: Inactive]"
	return "[GameState: Turn %d, Phase: %s, Player %d]" % [
		turn_manager.turn_number,
		turn_manager.get_phase_string(),
		turn_manager.current_player_index + 1
	]
