class_name CombatUI extends CanvasLayer

signal fight_confirmed(proposal: CombatProposal)
signal fight_cancelled

@onready var unit_panel: Control = %UnitPanel
@onready var unit_name_label: RichTextLabel = %UnitName
@onready var level_number: StylizedNumberDisplay = %LevelNumber
@onready var health_chip_bar: ChipBar = %HealthChipBar
@onready var health_number: StylizedNumberDisplay = %HealthNumber
@onready var sp_chip_bar: ChipBar = %SPChipBar
@onready var sp_number: StylizedNumberDisplay = %SPNumber
@onready var fs_chip_bar: ChipBar = %FSChipBar
@onready var fs_number: StylizedNumberDisplay = %FSNumber

@onready var background_tint: ColorRect = %BackgroundTint
@onready var proposal_panel: PanelContainer = %CombatProposalPanel
@onready var atk_name_label: Label = %AttackerNameLabel
@onready var atk_hp_bar: ProgressBar = %AttackerHPBar
@onready var atk_atk_label: Label = %AttackerATKLabel
@onready var atk_def_label: Label = %AttackerDEFLabel
@onready var atk_hit_label: Label = %AttackerHITLabel
@onready var atk_spd_label: Label = %AttackerSPDLabel
@onready var def_name_label: Label = %DefenderNameLabel
@onready var def_hp_bar: ProgressBar = %DefenderHPBar
@onready var def_atk_label: Label = %DefenderATKLabel
@onready var def_def_label: Label = %DefenderDEFLabel
@onready var def_hit_label: Label = %DefenderHITLabel
@onready var def_spd_label: Label = %DefenderSPDLabel
@onready var fight_button: Button = %FightButton
@onready var cancel_button: Button = %CancelButton
@onready var atk_tactic_select: OptionButton = %AttackerTacticSelect
@onready var def_tactic_select: OptionButton = %DefenderTacticSelect

var _selected_unit: DeployedUnit
var _current_proposal: CombatProposal
var combat_system: CombatSystem

func _ready() -> void:
	unit_panel.visible = false
	proposal_panel.visible = false
	fight_button.pressed.connect(_on_fight_pressed)
	cancel_button.pressed.connect(_on_cancel_pressed)
	atk_tactic_select.item_selected.connect(_on_atk_tactic_selected)
	def_tactic_select.item_selected.connect(_on_def_tactic_selected)
	for deployed: DeployedUnit in get_tree().get_nodes_in_group("deployed_units"):
		deployed.unit_selected_changed.connect(_on_unit_selected_changed)
		deployed.unit_died.connect(_on_unit_died)
	get_tree().node_added.connect(_on_node_added)

func _on_node_added(node: Node) -> void:
	if node is DeployedUnit and node.is_in_group("deployed_units"):
		if not node.unit_selected_changed.is_connected(_on_unit_selected_changed):
			node.unit_selected_changed.connect(_on_unit_selected_changed)
		if not node.unit_died.is_connected(_on_unit_died):
			node.unit_died.connect(_on_unit_died)

func _on_unit_died(deployed: DeployedUnit) -> void:
	if _selected_unit == deployed:
		_selected_unit = null
		unit_panel.visible = false
	if _current_proposal:
		if _current_proposal.attacker.deployed == deployed or _current_proposal.defender.deployed == deployed:
			_hide_proposal()

func _process(_delta: float) -> void:
	if _selected_unit and is_instance_valid(_selected_unit):
		_refresh_unit_panel()

func _unhandled_input(event: InputEvent) -> void:
	if proposal_panel.visible and event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_RIGHT:
		_hide_proposal()
		fight_cancelled.emit()
		get_viewport().set_input_as_handled()

func _on_unit_selected_changed(deployed: DeployedUnit, selected: bool) -> void:
	if selected:
		_selected_unit = deployed
		_refresh_unit_panel()
		unit_panel.visible = true
	else:
		_selected_unit = null
		unit_panel.visible = false

func _refresh_unit_panel() -> void:
	var stats := _selected_unit.current_stats
	unit_name_label.text = "[b]%s[/b]" % _selected_unit.unit.info.name
	level_number.value = stats.level
	health_chip_bar.max_value = stats.max_hp
	health_chip_bar.value = stats.current_hp
	health_number.value = stats.current_hp
	sp_chip_bar.max_value = stats.max_sp
	sp_chip_bar.value = stats.current_sp
	sp_number.value = stats.current_sp
	fs_chip_bar.max_value = stats.max_fs
	fs_chip_bar.value = stats.current_fs
	fs_number.value = stats.current_fs

func show_proposal(proposal: CombatProposal) -> void:
	_current_proposal = proposal
	_populate_tactic_select(atk_tactic_select, proposal.attacker)
	_populate_tactic_select(def_tactic_select, proposal.defender)
	_refresh_stats()
	background_tint.visible = true
	proposal_panel.visible = true

func _hide_proposal() -> void:
	background_tint.visible = false
	proposal_panel.visible = false
	_current_proposal = null

func _on_fight_pressed() -> void:
	if _current_proposal:
		var proposal := _current_proposal
		_hide_proposal()
		fight_confirmed.emit(proposal)

func _on_cancel_pressed() -> void:
	_hide_proposal()
	fight_cancelled.emit()


func _populate_tactic_select(button: OptionButton, combatant: CombatProposal.CombatantStats) -> void:
	button.clear()
	var selected_idx := 0
	for i in combatant.available_tactics.size():
		var tactic := combatant.available_tactics[i]
		button.add_item(tactic.tactic_name)
		if tactic == combatant.selected_tactic:
			selected_idx = i
	button.selected = selected_idx
	var is_player := combatant.deployed.unit.allegiance.type == UnitAllegiance.AllegianceType.PLAYER
	button.disabled = not is_player


func _refresh_stats() -> void:
	var atk := _current_proposal.attacker
	var def := _current_proposal.defender
	atk_name_label.text = atk.deployed.unit.info.name
	atk_hp_bar.max_value = atk.max_hp
	atk_hp_bar.value = atk.hp
	atk_atk_label.text = "ATK: %d" % atk.atk
	atk_def_label.text = "DEF: %d" % atk.def
	atk_hit_label.text = "HIT: %d%%" % atk.hit
	atk_spd_label.text = "SPD: %d" % atk.spd
	def_name_label.text = def.deployed.unit.info.name
	def_hp_bar.max_value = def.max_hp
	def_hp_bar.value = def.hp
	def_atk_label.text = "ATK: %d" % def.atk
	def_def_label.text = "DEF: %d" % def.def
	def_hit_label.text = "HIT: %d%%" % def.hit
	def_spd_label.text = "SPD: %d" % def.spd


func _on_atk_tactic_selected(index: int) -> void:
	if not _current_proposal or not combat_system:
		return
	var tactic := _current_proposal.attacker.available_tactics[index]
	combat_system.update_tactic(_current_proposal, true, tactic)
	_refresh_stats()


func _on_def_tactic_selected(index: int) -> void:
	if not _current_proposal or not combat_system:
		return
	var tactic := _current_proposal.defender.available_tactics[index]
	combat_system.update_tactic(_current_proposal, false, tactic)
	_refresh_stats()
