extends Node2D

signal tile_selected(tile: Node2D)

@export var tile_type: int = 0:
	set = _set_tile_type
var grid_position: Vector2i
var is_selected: bool = false:
	set = _set_selected
var is_highlighted: bool = false:
	set = _set_highlighted
var original_scale: Vector2 = Vector2.ONE  # Store the original scale for the board

@onready var sprite: Sprite2D = $Sprite2D

# Target size for each tile to fit in the 54x54 grid cells
const TILE_SIZE = 48  # Slightly smaller than 54 to leave some padding

# All available gem textures
var all_gem_textures: Array[Texture2D] = [
	preload("res://assets/sprites/gems/bg_19.png"),  # 0 - Blue gem
	preload("res://assets/sprites/gems/dg_19.png"),  # 1 - Dark gem
	preload("res://assets/sprites/gems/gg_19.png"),  # 2 - Green gem
	preload("res://assets/sprites/gems/mg_19.png"),  # 3 - Magenta gem
	preload("res://assets/sprites/gems/rg_19.png"),  # 4 - Red gem
	preload("res://assets/sprites/gems/yg_19.png"),  # 5 - Yellow gem
	preload("res://assets/sprites/gems/pg_19.png"),  # 6 - Purple gem
	preload("res://assets/sprites/gems/sg_19.png"),  # 7 - Silver gem
]

# Currently active gem types (indices into all_gem_textures)
var active_gem_types: Array[int] = []  # Will be set from TileManager


func _set_tile_type(value: int) -> void:
	tile_type = value
	# Fixed: Add sprite null check to prevent crashes during initialization
	if not sprite:
		return
	if value >= 0 and value < active_gem_types.size():
		var texture_index = active_gem_types[value]
		sprite.texture = all_gem_textures[texture_index]
		_scale_sprite_to_fit()
	else:
		DebugManager.log_error(
			(
				"Invalid tile type: "
				+ str(value)
				+ ". Available types: 0-"
				+ str(active_gem_types.size() - 1)
			),
			"Match3"
		)


func _scale_sprite_to_fit() -> void:
	# Fixed: Add additional null checks
	if sprite and sprite.texture:
		var texture_size = sprite.texture.get_size()
		var max_dimension = max(texture_size.x, texture_size.y)
		var scale_factor = TILE_SIZE / max_dimension
		original_scale = Vector2(scale_factor, scale_factor)
		sprite.scale = original_scale
		DebugManager.log_debug(
			(
				"Set original scale to %s for tile (%d,%d)"
				% [original_scale, grid_position.x, grid_position.y]
			),
			"Match3"
		)


func set_active_gem_types(gem_indices: Array[int]) -> void:
	if not gem_indices or gem_indices.is_empty():
		DebugManager.log_error("Empty gem indices array provided", "Tile")
		return

	active_gem_types = gem_indices.duplicate()

	# Validate all gem indices are within bounds
	for gem_index in active_gem_types:
		if gem_index < 0 or gem_index >= all_gem_textures.size():
			DebugManager.log_error(
				(
					"Invalid gem index: %d (valid range: 0-%d)"
					% [gem_index, all_gem_textures.size() - 1]
				),
				"Tile"
			)
			# Use default fallback
			active_gem_types = [0, 1, 2, 3, 4]
			break

	# Re-validate current tile type
	if tile_type >= active_gem_types.size():
		# Generate a new random tile type within valid range
		tile_type = randi() % active_gem_types.size()

	_set_tile_type(tile_type)


func get_active_gem_count() -> int:
	return active_gem_types.size()


func add_gem_type(gem_index: int) -> bool:
	if gem_index < 0 or gem_index >= all_gem_textures.size():
		DebugManager.log_error("Invalid gem index: %d" % gem_index, "Tile")
		return false

	if not active_gem_types.has(gem_index):
		active_gem_types.append(gem_index)
		return true

	return false


func remove_gem_type(gem_index: int) -> bool:
	var type_index = active_gem_types.find(gem_index)
	if type_index == -1:
		return false

	if active_gem_types.size() <= 2:  # Keep at least 2 gem types
		DebugManager.log_warn("Cannot remove gem type - minimum 2 types required", "Tile")
		return false

	active_gem_types.erase(gem_index)

	# Update tile if it was using the removed type
	if tile_type >= active_gem_types.size():
		tile_type = 0
		_set_tile_type(tile_type)

	return true


func _set_selected(value: bool) -> void:
	var old_value = is_selected
	is_selected = value
	DebugManager.log_debug(
		(
			"Tile (%d,%d) selection changed: %s -> %s"
			% [grid_position.x, grid_position.y, old_value, value]
		),
		"Match3"
	)
	_update_visual_feedback()


func _set_highlighted(value: bool) -> void:
	var old_value = is_highlighted
	is_highlighted = value
	DebugManager.log_debug(
		(
			"Tile (%d,%d) highlight changed: %s -> %s"
			% [grid_position.x, grid_position.y, old_value, value]
		),
		"Match3"
	)
	_update_visual_feedback()


func _update_visual_feedback() -> void:
	if not sprite:
		return

	# Determine target values based on priority: selected > highlighted > normal
	var target_modulate: Color
	var target_scale: Vector2
	var scale_multiplier: float

	if is_selected:
		# Selected: bright and larger than original board size
		target_modulate = Color(1.2, 1.2, 1.2, 1.0)
		scale_multiplier = UIConstants.TILE_SELECTED_SCALE
		DebugManager.log_debug(
			(
				"SELECTING tile (%d,%d): target scale %.2fx, current scale %s"
				% [grid_position.x, grid_position.y, scale_multiplier, sprite.scale]
			),
			"Match3"
		)
	elif is_highlighted:
		# Highlighted: subtle glow and larger than original board size
		target_modulate = Color(1.1, 1.1, 1.1, 1.0)
		scale_multiplier = UIConstants.TILE_HIGHLIGHTED_SCALE
		DebugManager.log_debug(
			(
				"HIGHLIGHTING tile (%d,%d): target scale %.2fx, current scale %s"
				% [grid_position.x, grid_position.y, scale_multiplier, sprite.scale]
			),
			"Match3"
		)
	else:
		# Normal state: white and original board size
		target_modulate = Color.WHITE
		scale_multiplier = UIConstants.TILE_NORMAL_SCALE
		DebugManager.log_debug(
			(
				"NORMALIZING tile (%d,%d): target scale %.2fx, current scale %s"
				% [grid_position.x, grid_position.y, scale_multiplier, sprite.scale]
			),
			"Match3"
		)

	# Calculate target scale relative to original board scale
	target_scale = original_scale * scale_multiplier

	# Apply modulate immediately
	sprite.modulate = target_modulate

	# Only animate scale if it's actually changing
	if sprite.scale != target_scale:
		DebugManager.log_debug(
			(
				"Animating scale from %s to %s for tile (%d,%d)"
				% [sprite.scale, target_scale, grid_position.x, grid_position.y]
			),
			"Match3"
		)

		var tween = create_tween()
		tween.tween_property(sprite, "scale", target_scale, 0.15)

		# Add completion callback for debugging
		tween.tween_callback(_on_scale_animation_completed.bind(target_scale))
	else:
		DebugManager.log_debug(
			"No scale change needed for tile (%d,%d)" % [grid_position.x, grid_position.y], "Match3"
		)


func _on_scale_animation_completed(expected_scale: Vector2) -> void:
	DebugManager.log_debug(
		(
			"Scale animation completed for tile (%d,%d): expected %s, actual %s"
			% [grid_position.x, grid_position.y, expected_scale, sprite.scale]
		),
		"Match3"
	)


func force_reset_visual_state() -> void:
	# Force reset all visual states - debug function
	is_selected = false
	is_highlighted = false
	if sprite:
		sprite.modulate = Color.WHITE
		sprite.scale = original_scale  # Reset to original board scale, not 1.0
	DebugManager.log_debug(
		(
			"Forced visual reset on tile (%d,%d) to original scale %s"
			% [grid_position.x, grid_position.y, original_scale]
		),
		"Match3"
	)


# Handle input for tile selection
func _input(event: InputEvent) -> void:
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
			# Check if the mouse click is within the tile's bounds
			var local_position = to_local(get_global_mouse_position())
			var sprite_rect = Rect2(-TILE_SIZE / 2.0, -TILE_SIZE / 2.0, TILE_SIZE, TILE_SIZE)

			if sprite_rect.has_point(local_position):
				tile_selected.emit(self)
				get_viewport().set_input_as_handled()


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	add_to_group("tiles")  # Add to group for gem pool management

	# Initialize with default gem pool if not already set
	if active_gem_types.is_empty():
		active_gem_types = [0, 1, 2, 3, 4]  # Default to first 5 gems

	_set_tile_type(tile_type)
