class_name BaseMonster
extends PathFollow3D

## 기본 몬스터 클래스 (Path3D 상하위에서 경로를 따라 회전하며 피격/사망 처리됨)

# 몬스터 능력치 설정
@export var speed: float = 2.0
var max_hp: float = 100.0
var current_hp: float = 100.0
var gold_reward: int = 15

var is_dead: bool = false
var _hp_bar: ProgressBar = null
var _model_instance: Node3D = null
var _model_anim_player: AnimationPlayer = null
var _last_anim_state: String = ""

func _ready() -> void:
	# 몬스터 그룹 등록
	add_to_group("monsters")
	# PathFollow3D 루프 설정 활성화 (경로 끝 도달 시 처음으로 돌아감)
	loop = true
	
	# 자식 노드 중 3D 모델(noble_man 등) 노드 자동 탐색 및 초기화 (base_unit.gd 매커니즘 준수)
	var model_names: Array[String] = ["noble_man"]
	var detected_model_node: Node3D = null
	var detected_model_name: String = ""
	
	for m_name: String in model_names:
		var node: Node3D = get_node_or_null(m_name) as Node3D
		if node:
			detected_model_node = node
			detected_model_name = m_name
			break
			
	if detected_model_node:
		_model_instance = detected_model_node
		
		if detected_model_name == "noble_man":
			_apply_noble_man_skin(_model_instance)
			
		_model_anim_player = _find_animation_player(_model_instance)
		if _model_anim_player:
			print("BaseMonster: Linked model AnimationPlayer: ", detected_model_name)
			
			# 모델명_animations.tres 라이브러리를 동적으로 로드하여 등록 (base_unit.gd 방식 준수)
			var anim_lib_path: String = "res://assets/models/monsters/" + detected_model_name + "/" + detected_model_name + "_animations.tres"
			if ResourceLoader.exists(anim_lib_path):
				var lib: AnimationLibrary = load(anim_lib_path) as AnimationLibrary
				if lib:
					_model_anim_player.add_animation_library(detected_model_name, lib)
					print("BaseMonster: Loaded and registered ", detected_model_name, " animations library successfully.")
			
			# 초기 Idle 애니메이션 재생 시도
			var init_idle: String = detected_model_name + "/Idle"
			if _model_anim_player.has_animation(init_idle):
				_model_anim_player.play(init_idle)
			elif _model_anim_player.has_animation("Armature|Idle"):
				_model_anim_player.play("Armature|Idle")

## 몬스터 자식 메쉬에 noble_man_0.png 텍스처를 입히는 재귀 함수
func _apply_noble_man_skin(node: Node) -> void:
	if node is MeshInstance3D:
		var mesh_inst: MeshInstance3D = node as MeshInstance3D
		var texture_path: String = "res://assets/models/monsters/noble_man/noble_man_0.png"
		if ResourceLoader.exists(texture_path):
			var texture: Texture2D = load(texture_path) as Texture2D
			if texture:
				var mat: StandardMaterial3D = StandardMaterial3D.new()
				mat.albedo_texture = texture
				mat.roughness = 0.5
				mesh_inst.material_override = mat
	for child: Node in node.get_children():
		_apply_noble_man_skin(child)


func _physics_process(delta: float) -> void:
	if GameManager.is_game_over or is_dead:
		if _model_anim_player and _model_anim_player.is_playing():
			_model_anim_player.stop()
		return
		
	# 경로 이동 거리 갱신
	progress += speed * delta
	
	# 걷는 애니메이션 갱신
	_update_monster_animation()

## 몬스터 초기화 (StageManager에 의해 스폰 시 호출됨)
func initialize_monster(hp: float, reward: int) -> void:
	max_hp = hp
	current_hp = hp
	gold_reward = reward
	is_dead = false
	
	# 체력바 생성
	_create_hp_bar()

## 피해 가하기
func take_damage(amount: float) -> void:
	if is_dead:
		return
		
	current_hp = maxf(0.0, current_hp - amount)
	if _hp_bar:
		_hp_bar.value = current_hp
		
	print("Monster ", name, " took ", amount, " damage. HP: ", current_hp, "/", max_hp)
	
	if current_hp <= 0.0:
		_die()

## 사망 처리
func _die() -> void:
	is_dead = true
	
	# 골드 보상 획득
	GameManager.add_gold(gold_reward)
	
	# 필드 활성 몬스터 수 감소
	GameManager.decrement_monster_count()
	
	print("Monster ", name, " died! Rewarded ", gold_reward, " gold.")
	
	# 씬에서 제거
	queue_free()

## 체력바 UI 생성 및 3D 공간 머리 위 빌보드 배치
func _create_hp_bar() -> void:
	# 1. SubViewport 생성 (2D UI를 3D 텍스처로 렌더링하기 위함)
	var viewport: SubViewport = SubViewport.new()
	viewport.size = Vector2i(100, 12)
	viewport.transparent_bg = true
	viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
	add_child(viewport)
	
	# 2. ProgressBar 생성
	_hp_bar = ProgressBar.new()
	_hp_bar.size = Vector2(100, 12)
	_hp_bar.show_percentage = false
	_hp_bar.min_value = 0.0
	_hp_bar.max_value = max_hp
	_hp_bar.value = current_hp
	
	# 스타일박스를 사용하여 빨간색 HP 게이지 디자인 커스텀
	var style_bg: StyleBoxFlat = StyleBoxFlat.new()
	style_bg.bg_color = Color(0.15, 0.15, 0.15, 0.8) # 어두운 회색 배경
	style_bg.set_corner_radius_all(2)
	
	var style_fg: StyleBoxFlat = StyleBoxFlat.new()
	style_fg.bg_color = Color(0.9, 0.1, 0.1, 1.0) # 강렬한 빨간색 fill
	style_fg.set_corner_radius_all(2)
	
	_hp_bar.add_theme_stylebox_override("background", style_bg)
	_hp_bar.add_theme_stylebox_override("fill", style_fg)
	viewport.add_child(_hp_bar)
	
	# 3. Sprite3D 생성 (Viewport의 2D 렌더링 텍스처를 3D 공간에 띄움)
	var sprite: Sprite3D = Sprite3D.new()
	sprite.billboard = BaseMaterial3D.BILLBOARD_ENABLED # 카메라를 항상 마주하도록 설정
	sprite.position = Vector3(0.0, 0.15, 0.0) # 몬스터 발밑 오프셋
	sprite.texture = viewport.get_texture()
	sprite.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF # 그림자 연산 제외
	sprite.no_depth_test = false # 지형이나 다른 장막 뒤에 가려지도록 설정
	add_child(sprite)

## 몬스터 이동 상태에 맞춘 애니메이션 재생 제어
func _update_monster_animation() -> void:
	if not _model_anim_player:
		return
		
	# 기본 트랙 이름 탐색 순서: 동적 로드된 라이브러리(noble_man/walking) -> FBX 내장 트랙(Armature|Walking)
	var anim_name: String = ""
	var model_name: String = ""
	if _model_instance:
		model_name = _model_instance.name.to_lower()
		
	var lib_walking: String = model_name + "/Walking"
	if _model_anim_player.has_animation(lib_walking):
		anim_name = lib_walking
	elif _model_anim_player.has_animation("Armature|Walking"):
		anim_name = "Armature|Walking"
		
	if anim_name != "":
		# 걷는 애니메이션 루프 활성화
		var anim: Animation = _model_anim_player.get_animation(anim_name)
		if anim:
			anim.loop_mode = Animation.LOOP_LINEAR
			
		if _last_anim_state != "walking":
			_last_anim_state = "walking"
			_model_anim_player.play(anim_name, -1, 1.2) # 1.2배속 재생

## 헬퍼: 자식 노드 중 AnimationPlayer 탐색
func _find_animation_player(node: Node) -> AnimationPlayer:
	if node is AnimationPlayer:
		return node as AnimationPlayer
	for child: Node in node.get_children():
		var res: AnimationPlayer = _find_animation_player(child)
		if res:
			return res
	return null
