extends Node3D

@export var day_length := 120.0 # seconds for full rotation
@export var start_light_angle := -90.0
@export var show_spawn_dialog := true
@export_multiline var spawn_dialog_text := "Welcome to Promiscuity.\n\nPress E to close this message."
@export var spawn_dialog_auto_close_seconds := 4.0
var end_light_angle = start_light_angle + 360.0
var start_radians = start_light_angle * PI / 180
var time := 0.0

@onready var sun := $DirectionalLight3D
@onready var _player: Node = $Player
@onready var _quest_text: RichTextLabel = $PhoneUI/Control/PhoneFrame/QuestText

const FIRST_QUEST_ID := "first_drive"
const QUEST_PROMPT_META_PREFIX := "quest_intro_prompt_shown_"
const SPAWN_DIALOG_META_KEY := "level_spawn_dialog_shown"
const FIRST_QUEST := {
	"id": FIRST_QUEST_ID,
	"title": "RepoBot's First Task",
	"description": "Get familiar with movement and vehicles.",
	"steps": [
		{
			"id": "enter_vehicle",
			"text": "Get in the car (E).",
			"complete_event": "entered_vehicle",
		},
		{
			"id": "reach_checkpoint",
			"text": "Drive the car into the checkpoint marker.",
			"complete_event": "reach_checkpoint",
		},
	],
}

func _ready() -> void:
	_setup_quests()
	if _should_show_spawn_dialog() and DialogSystem and DialogSystem.has_method("show_text"):
		await get_tree().process_frame
		DialogSystem.show_text(spawn_dialog_text)
		_mark_spawn_dialog_shown()
		if spawn_dialog_auto_close_seconds > 0.0:
			await get_tree().create_timer(spawn_dialog_auto_close_seconds).timeout
			if DialogSystem and DialogSystem.has_method("close_if_text"):
				DialogSystem.close_if_text(spawn_dialog_text)
	_show_quest_intro_dialog()

func _process(delta):
	time = fmod((time + delta), day_length)
	var t = time / day_length

	# Rotate sun around X axis
	var angle = lerp(start_light_angle, end_light_angle, t) # sunrise → sunset → night → sunrise
	sun.rotation_degrees.x = angle

	# Adjust intensity
	var curSin = -sin((t * TAU) + start_radians)
	var energy = clamp((curSin * 1.0) + 0.2, 0.0, 1.2)
	sun.light_energy = energy


func _setup_quests() -> void:
	if QuestManager == null:
		return
	if not QuestManager.has_quest(FIRST_QUEST_ID):
		QuestManager.register_quest(FIRST_QUEST)
	if not QuestManager.is_active_quest(FIRST_QUEST_ID) and not QuestManager.is_quest_completed(FIRST_QUEST_ID):
		QuestManager.start_quest(FIRST_QUEST_ID)
	if not QuestManager.is_connected("quest_state_changed", Callable(self, "_refresh_quest_ui")):
		QuestManager.quest_state_changed.connect(_refresh_quest_ui)
	if _player and _player.has_signal("vehicle_entered"):
		if not _player.is_connected("vehicle_entered", Callable(self, "_on_player_vehicle_entered")):
			_player.vehicle_entered.connect(_on_player_vehicle_entered)
	_refresh_quest_ui()


func _on_player_vehicle_entered(_vehicle: Node) -> void:
	if QuestManager:
		QuestManager.emit_event(&"entered_vehicle")


func _refresh_quest_ui() -> void:
	if _quest_text == null or QuestManager == null:
		return
	var state: Dictionary = QuestManager.get_active_quest_state()
	if not bool(state.get("active", false)):
		_quest_text.text = "No active quest."
		return
	var title := String(state.get("title", "Quest"))
	if bool(state.get("completed", false)):
		_quest_text.text = "[b]%s[/b]\nComplete." % title
		return
	var step_index: int = int(state.get("current_step_index", 0))
	var total_steps: int = int(state.get("total_steps", 0))
	var step_text := String(state.get("current_step_text", ""))
	_quest_text.text = "[b]%s[/b]\nStep %d/%d\n%s" % [title, step_index + 1, total_steps, step_text]


func _show_quest_intro_dialog() -> void:
	if QuestManager == null:
		return
	var state: Dictionary = QuestManager.get_active_quest_state()
	if not bool(state.get("active", false)) or bool(state.get("completed", false)):
		return
	var quest_id := String(state.get("quest_id", "")).strip_edges()
	var step_id := String(state.get("current_step_id", "")).strip_edges()
	var step_text := String(state.get("current_step_text", ""))
	if quest_id.is_empty() or step_id.is_empty() or step_text.is_empty():
		return
	var prompt_key := "%s%s_%s" % [QUEST_PROMPT_META_PREFIX, quest_id, step_id]
	if QuestManager.has_meta(prompt_key) and bool(QuestManager.get_meta(prompt_key)):
		return
	if DialogSystem and DialogSystem.has_method("show_text"):
		DialogSystem.show_text("RepoBot: New task assigned.\n\n%s" % step_text)
		QuestManager.set_meta(prompt_key, true)


func _should_show_spawn_dialog() -> bool:
	if not show_spawn_dialog:
		return false
	if QuestManager == null:
		return true
	if not QuestManager.has_meta(SPAWN_DIALOG_META_KEY):
		return true
	return not bool(QuestManager.get_meta(SPAWN_DIALOG_META_KEY))


func _mark_spawn_dialog_shown() -> void:
	if QuestManager == null:
		return
	QuestManager.set_meta(SPAWN_DIALOG_META_KEY, true)
