extends Control
class_name CharacterSheet
## Character sheet / spellbook that displays player stats, weapons, and abilities
## Opens with Tab key

# References
@onready var stats_container: VBoxContainer = $Panel/MarginContainer/VBoxContainer/HBoxContainer/LeftPage/ScrollContainer/StatsContainer
@onready var weapons_container: VBoxContainer = $Panel/MarginContainer/VBoxContainer/HBoxContainer/RightPage/ScrollContainer/ContentContainer/WeaponsContainer
@onready var abilities_container: VBoxContainer = $Panel/MarginContainer/VBoxContainer/HBoxContainer/RightPage/ScrollContainer/ContentContainer/AbilitiesContainer

# Player reference
var player: Character = null

# Preview mode: renders from a loadout dictionary instead of a live player.
# Used by the outfitting screen at character creation.
# preview_data keys: "nick" (String), "main" (WeaponData or null), "offhand" (WeaponData or null)
var preview_mode: bool = false
var preview_data: Dictionary = {}

# Character defaults shown in preview (match player.gd export defaults)
const PREVIEW_MAX_HEALTH := 100.0
const PREVIEW_ATTACK_DAMAGE := 10.0
const PREVIEW_ATTACK_RANGE := 3.0
const PREVIEW_ATTACK_COOLDOWN := 0.5
const PREVIEW_DASH_COOLDOWN := 4.0
const PREVIEW_DASH_DURATION := 0.25
const PREVIEW_DASH_MULTIPLIER := 2.0

# Visibility
var is_visible: bool = false

func _ready():
	if preview_mode:
		_configure_preview_layout()
		show()
		is_visible = true
		refresh_all()
	else:
		# Start hidden (in-game Tab toggle behavior)
		hide()
		is_visible = false

func _input(event):
	# Embedded preview never toggles - it's part of the outfitting screen
	if preview_mode:
		return

	# Close on Escape press if open
	if event.is_action_pressed("quit") and is_visible:
		toggle_sheet()
		get_viewport().set_input_as_handled()
		return

	# Toggle on Tab press
	if event.is_action_pressed("toggle_character_sheet"):
		toggle_sheet()
		get_viewport().set_input_as_handled()

## Set the player reference and update display
func set_player(p: Character):
	player = p
	if player:
		refresh_all()

## Feed the sheet a loadout to preview (outfitting screen).
## Safe to call before or after the sheet enters the tree.
func set_preview(data: Dictionary):
	preview_mode = true
	preview_data = data
	if is_inside_tree():
		refresh_all()

## Re-shape the fullscreen overlay into an embeddable panel:
## no dark backdrop, panel fills the space its parent gives it.
func _configure_preview_layout():
	mouse_filter = Control.MOUSE_FILTER_IGNORE
	var backdrop = get_node_or_null("DarkBackground")
	if backdrop:
		backdrop.hide()
	var panel = get_node_or_null("Panel")
	if panel:
		panel.set_anchors_preset(Control.PRESET_FULL_RECT)
		panel.offset_left = 0
		panel.offset_top = 0
		panel.offset_right = 0
		panel.offset_bottom = 0
	var title = get_node_or_null("Panel/MarginContainer/VBoxContainer/TitleLabel")
	if title:
		title.text = "YOUR GLADIATOR"
	var close_hint = get_node_or_null("Panel/MarginContainer/VBoxContainer/CloseHint")
	if close_hint:
		close_hint.hide()

## Toggle character sheet visibility
func toggle_sheet():
	is_visible = !is_visible
	if is_visible:
		show()
		refresh_all()
		# Release mouse when opening sheet
		Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
	else:
		hide()
		# Recapture mouse when closing sheet
		if player and player.is_multiplayer_authority():
			Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

## Refresh all data in the sheet
func refresh_all():
	if not player and not preview_mode:
		return

	_refresh_stats()
	_refresh_weapons()
	_refresh_abilities()

## Refresh player stats
func _refresh_stats():
	if not stats_container:
		return

	# Clear existing stats
	for child in stats_container.get_children():
		child.queue_free()

	# Add title
	var title = Label.new()
	title.text = "CHARACTER STATS"
	title.add_theme_font_size_override("font_size", 24)
	title.add_theme_color_override("font_color", Color(1.0, 0.8, 0.0))
	stats_container.add_child(title)

	# Spacer
	var spacer1 = Control.new()
	spacer1.custom_minimum_size = Vector2(0, 10)
	stats_container.add_child(spacer1)

	# Resolve stats from either the live player or the preview loadout
	var player_name: String
	var current_hp: int
	var max_hp: int
	var atk_damage: float
	var atk_range: float
	var atk_cooldown: float

	if preview_mode:
		player_name = preview_data.get("nick", "Gladiator")
		if player_name.strip_edges() == "":
			player_name = "Gladiator"
		current_hp = int(PREVIEW_MAX_HEALTH)
		max_hp = int(PREVIEW_MAX_HEALTH)
		# Combat stats come from the selected main weapon, or bare fists
		var main_weapon = preview_data.get("main")
		if main_weapon is WeaponData:
			atk_damage = main_weapon.damage
			atk_range = main_weapon.attack_range
			atk_cooldown = main_weapon.attack_cooldown
		else:
			atk_damage = PREVIEW_ATTACK_DAMAGE
			atk_range = PREVIEW_ATTACK_RANGE
			atk_cooldown = PREVIEW_ATTACK_COOLDOWN
	else:
		var player_id = player.name.to_int()
		player_name = "Player"
		if Network.players.has(player_id):
			player_name = Network.players[player_id]["nick"]
		current_hp = int(player.current_health)
		max_hp = int(player.max_health)
		atk_damage = player.attack_damage
		atk_range = player.attack_range
		atk_cooldown = player.attack_cooldown

	_add_stat_label("Name: " + player_name)
	_add_stat_label("Level: 1")  # Hardcoded for now
	_add_stat_label("")

	# Health stats
	_add_stat_label("=== HEALTH ===", Color(0.8, 0.8, 0.8))
	_add_stat_label("Current HP: " + str(current_hp))
	_add_stat_label("Max HP: " + str(max_hp))
	var hp_percent = int(float(current_hp) / max_hp * 100) if max_hp > 0 else 0
	_add_stat_label("Health: " + str(hp_percent) + "%")
	_add_stat_label("")

	# Movement stats (class constants - same for live and preview)
	_add_stat_label("=== MOVEMENT ===", Color(0.8, 0.8, 0.8))
	_add_stat_label("Walk Speed: " + str(Character.NORMAL_SPEED))
	_add_stat_label("Sprint Speed: " + str(Character.SPRINT_SPEED))
	_add_stat_label("Jump Power: " + str(Character.JUMP_VELOCITY))
	_add_stat_label("")

	# Combat stats
	_add_stat_label("=== COMBAT ===", Color(0.8, 0.8, 0.8))
	if preview_mode and preview_data.get("main") is WeaponData:
		_add_stat_label("Weapon Damage: " + str(atk_damage))
	else:
		_add_stat_label("Base Damage: " + str(atk_damage))
	_add_stat_label("Attack Range: " + str(atk_range))
	_add_stat_label("Attack Cooldown: " + str(atk_cooldown) + "s")

	# Off-hand block bonus (preview only - handy when choosing a shield)
	if preview_mode:
		var offhand = preview_data.get("offhand")
		if offhand is WeaponData and offhand.can_block:
			_add_stat_label("")
			_add_stat_label("=== DEFENSE ===", Color(0.8, 0.8, 0.8))
			_add_stat_label("Block Reduction: " + str(int(offhand.block_reduction * 100)) + "%")

## Refresh equipped weapons
func _refresh_weapons():
	if not weapons_container:
		return

	# Clear existing
	for child in weapons_container.get_children():
		child.queue_free()

	# Add title
	var title = Label.new()
	title.text = "EQUIPPED WEAPONS"
	title.add_theme_font_size_override("font_size", 20)
	title.add_theme_color_override("font_color", Color(1.0, 0.8, 0.0))
	weapons_container.add_child(title)

	# Spacer
	var spacer = Control.new()
	spacer.custom_minimum_size = Vector2(0, 10)
	weapons_container.add_child(spacer)

	# Create horizontal container for weapon slots
	var slots_container = HBoxContainer.new()
	slots_container.add_theme_constant_override("separation", 15)
	weapons_container.add_child(slots_container)

	# Load weapon slot scene
	var weapon_slot_scene = load("res://level/ui/scenes/weapon_slot.tscn")
	if not weapon_slot_scene:
		push_error("[CharacterSheet] Failed to load weapon_slot.tscn")
		return

	# Resolve weapon data from preview loadout or live player
	var main_data: WeaponData = null
	var offhand_data: WeaponData = null
	if preview_mode:
		if preview_data.get("main") is WeaponData:
			main_data = preview_data["main"]
		if preview_data.get("offhand") is WeaponData:
			offhand_data = preview_data["offhand"]
	else:
		if player.equipped_weapon and player.equipped_weapon.weapon_data:
			main_data = player.equipped_weapon.weapon_data
		if player.equipped_offhand and player.equipped_offhand.weapon_data:
			offhand_data = player.equipped_offhand.weapon_data

	# Create main hand slot
	var main_hand_slot = weapon_slot_scene.instantiate()
	slots_container.add_child(main_hand_slot)

	if main_data:
		main_hand_slot.set_weapon(main_data, "Main Hand")
	else:
		main_hand_slot.clear_weapon()

	# Create off-hand slot
	var off_hand_slot = weapon_slot_scene.instantiate()
	slots_container.add_child(off_hand_slot)

	if offhand_data:
		off_hand_slot.set_weapon(offhand_data, "Off-Hand")
	else:
		off_hand_slot.clear_weapon()

## Refresh abilities list
func _refresh_abilities():
	if not abilities_container:
		return

	# Clear existing
	for child in abilities_container.get_children():
		child.queue_free()

	# Add title
	var title = Label.new()
	title.text = "ABILITIES"
	title.add_theme_font_size_override("font_size", 20)
	title.add_theme_color_override("font_color", Color(1.0, 0.8, 0.0))
	abilities_container.add_child(title)

	# Spacer
	var spacer = Control.new()
	spacer.custom_minimum_size = Vector2(0, 10)
	abilities_container.add_child(spacer)

	# Dash ability (defaults in preview, live values in game)
	var dash_cd = PREVIEW_DASH_COOLDOWN if preview_mode else player.dash_cooldown
	var dash_dur = PREVIEW_DASH_DURATION if preview_mode else player.dash_duration
	var dash_mult = PREVIEW_DASH_MULTIPLIER if preview_mode else player.dash_speed_multiplier

	_add_stat_label("--- DASH (F) ---", Color(0.8, 0.8, 0.8))
	_add_stat_label("Cooldown: " + str(dash_cd) + "s")
	_add_stat_label("Duration: " + str(dash_dur) + "s")
	_add_stat_label("Speed: " + str(dash_mult) + "x")
	_add_stat_label("Description: Dash in movement direction")
	if preview_mode:
		_add_stat_label("Status: READY", Color(0.0, 1.0, 0.0))
	else:
		var dash_remaining = player._dash_cooldown_timer
		if dash_remaining > 0:
			_add_stat_label("Ready in: " + str(ceil(dash_remaining)) + "s", Color(1.0, 0.5, 0.5))
		else:
			_add_stat_label("Status: READY", Color(0.0, 1.0, 0.0))

	# Spacer
	var spacer2 = Control.new()
	spacer2.custom_minimum_size = Vector2(0, 10)
	abilities_container.add_child(spacer2)

	# Jump ability
	_add_stat_label("--- JUMP (Space) ---", Color(0.8, 0.8, 0.8))
	_add_stat_label("Power: " + str(Character.JUMP_VELOCITY))
	_add_stat_label("Description: Jump into the air")
	_add_stat_label("Status: ALWAYS READY", Color(0.0, 1.0, 0.0))

## Helper to add a stat label
func _add_stat_label(text: String, color: Color = Color.WHITE):
	var label = Label.new()
	label.text = text
	label.add_theme_color_override("font_color", color)
	label.add_theme_color_override("font_outline_color", Color.BLACK)
	label.add_theme_constant_override("outline_size", 1)
	label.add_theme_font_size_override("font_size", 16)

	if stats_container:
		stats_container.add_child(label)
	elif weapons_container:
		weapons_container.add_child(label)
	elif abilities_container:
		abilities_container.add_child(label)
