#include "MenuManager.h"
#include <iostream>
#include <algorithm>
#include <string>

namespace ZL {

	static int questStatusPriority(Quest::QuestStatus status) {
		switch (status) {
		case Quest::QuestStatus::Active:    return 0;
		case Quest::QuestStatus::Available: return 1;
		case Quest::QuestStatus::Completed: return 2;
		case Quest::QuestStatus::Failed:    return 3;
		default:                            return 4;
		}
	}

	static std::array<float, 4> questStatusColor(Quest::QuestStatus status) {
		switch (status) {
		case Quest::QuestStatus::Completed: return { 0.25f, 0.95f, 0.35f, 1.0f };
		case Quest::QuestStatus::Failed:    return { 1.0f,  0.25f, 0.25f, 1.0f };
		case Quest::QuestStatus::Active:    return { 1.0f,  1.0f,  1.0f,  1.0f };
		case Quest::QuestStatus::Available: return { 0.86f, 0.86f, 0.86f, 1.0f };
		default:                            return { 0.45f, 0.45f, 0.45f, 1.0f };
		}
	}

	MenuManager::MenuManager(Renderer& iRenderer) :
		renderer(iRenderer)
	{
	}

	void MenuManager::setup(Inventory& inv, const std::string& zipFile) {
		inventory = &inv;

		hudRoot          = loadUiFromFile("resources/config2/hud.json",               renderer, zipFile);
		inventoryRoot    = loadUiFromFile("resources/config2/ui_inventory.json",       renderer, zipFile);
		questJournalRoot = loadUiFromFile("resources/config2/ui_quest_journal.json",   renderer, zipFile);

		questJournal.loadFromFile("resources/quests/quests.json", zipFile);

		enterGameplay();
	}

	void MenuManager::enterGameplay() {
		state = GameState::Gameplay;
		uiManager.replaceRoot(hudRoot);

		uiManager.setTextButtonCallback("inventory_button", [this](const std::string&) {
			openInventory();
			});

		uiManager.setTextButtonCallback("quest_journal_button", [this](const std::string&) {
			openQuestJournal();
			});
	}

	void MenuManager::openInventory() {
		state = GameState::Inventory;
		uiManager.pushMenuFromSavedRoot(inventoryRoot);

		uiManager.setTextButtonCallback("close_inventory_button", [this](const std::string&) {
			closeInventory();
			});

		const auto& items = inventory->getItems();
		std::string itemText;
		if (items.empty()) {
			itemText = "Inventory (Empty)";
		}
		else {
			itemText = "Inventory (" + std::to_string(items.size()) + " items)\n\n";
			for (size_t i = 0; i < items.size(); ++i) {
				itemText += std::to_string(i + 1) + ". " + items[i].name + "\n";
			}
		}
		uiManager.setText("inventory_items_text", itemText);
	}

	void MenuManager::closeInventory() {
		state = GameState::Gameplay;
		uiManager.popMenu();
	}

	void MenuManager::openQuestJournal() {
		state = GameState::QuestJournal;
		uiManager.pushMenuFromSavedRoot(questJournalRoot);

		uiManager.setTextButtonCallback("quest_close_button", [this](const std::string&) {
			closeQuestJournal();
			});

		for (int i = 0; i < 9; ++i) {
			const std::string slotName = "quest_slot_" + std::to_string(i);
			uiManager.setTextButtonCallback(slotName, [this, i](const std::string&) {
				selectQuestByIndex(i);
				});
		}

		refreshQuestJournalUi();
		if (!visibleQuestIds.empty()) {
			selectQuestByIndex(0);
		}
	}

	void MenuManager::closeQuestJournal() {
		state = GameState::Gameplay;
		selectedQuestIndex = -1;
		visibleQuestIds.clear();
		uiManager.popMenu();
	}

	void MenuManager::toggleQuestJournal() {
		std::cout << "[quest] toggleQuestJournal: " << (isQuestJournalOpen() ? "closing" : "opening") << std::endl;
		if (state == GameState::QuestJournal) {
			closeQuestJournal();
		}
		else {
			if (state == GameState::Inventory) {
				closeInventory();
			}
			openQuestJournal();
		}
	}

	void MenuManager::refreshQuestJournalUi() {
		visibleQuestIds.clear();
		auto quests = questJournal.getVisibleQuests();

		std::sort(quests.begin(), quests.end(), [](const Quest::QuestState* a, const Quest::QuestState* b) {
			const int pa = questStatusPriority(a->status);
			const int pb = questStatusPriority(b->status);
			if (pa != pb) return pa < pb;
			return a->orderIndex > b->orderIndex;
			});

		for (int i = 0; i < 9; ++i) {
			const std::string slotName = "quest_slot_" + std::to_string(i);

			if (i < static_cast<int>(quests.size())) {
				const auto* quest = quests[i];
				visibleQuestIds.push_back(quest->definition.id);

				const bool selected = (i == selectedQuestIndex);
				const std::string prefix = selected ? "> " : "  ";
				uiManager.setTextButtonText(slotName, prefix + quest->definition.title);
				uiManager.setTextButtonColor(slotName, questStatusColor(quest->status));
				uiManager.setNodeVisible(slotName, true);
			}
			else {
				uiManager.setTextButtonText(slotName, "");
				uiManager.setNodeVisible(slotName, false);
			}
		}
	}

	void MenuManager::selectQuestByIndex(int index) {
		if (index < 0 || index >= static_cast<int>(visibleQuestIds.size())) {
			return;
		}

		selectedQuestIndex = index;
		Quest::QuestState* quest = questJournal.findQuest(visibleQuestIds[index]);
		if (!quest) {
			return;
		}

		const auto& def = quest->definition;

		uiManager.setText("quest_middle_title_text", def.title);
		uiManager.setTextColor("quest_middle_title_text", questStatusColor(quest->status));

		const std::string meta = std::string("Category: ") + Quest::toString(def.category)
			+ " | Status: " + Quest::toString(quest->status)
			+ " | Level: " + std::to_string(def.recommendedLevel);
		uiManager.setText("quest_meta_text", meta);

		std::string objectivesText;
		for (size_t i = 0; i < def.objectives.size(); ++i) {
			const auto& obj = def.objectives[i];
			const bool isActive = static_cast<int>(i) == quest->activeObjectiveIndex;
			const std::string mark = obj.completed ? "[x] " : (isActive ? "> [ ] " : "[ ] ");
			objectivesText += mark + obj.text;
			if (i + 1 < def.objectives.size()) {
				objectivesText += "\n";
			}
		}
		uiManager.setText("quest_objectives_text", objectivesText);

		uiManager.setText("quest_lore_title_text", "Описание задания");
		uiManager.setText("quest_description_text", def.description);

		refreshQuestJournalUi();
	}

} // namespace ZL
