#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <cstdint>
#include <string>
#include <vector>
#include <algorithm>

#include "common/protocol.hpp"
#include "input/kmbox_net.hpp"
#include "input/human_curve.hpp"
#include "brain/bot_brain.hpp"

// ==========================================================
// AutoPOE2 - NpcInteractionHandler (Doc 39)
// Quản lý nhận diện NPC, đối thoại & chu trình tương tác tự hành
// ==========================================================

enum class NpcInteractState : uint8_t {
    Idle = 0,
    ApproachNpc = 1,   // Tiếp cận NPC mục tiêu trong cự ly tương tác
    OpenDialogue = 2,  // Bấm phím 'F' hoặc click chuột mở menu đối thoại
    SelectOption = 3,  // Nhấp chọn tùy chọn menu hoặc bấm Space bỏ qua hội thoại
    CloseDialogue = 4, // Đóng menu đối thoại (Space/ESC)
    Completed = 5,
    Failed = 6
};

inline const char* NpcInteractStateToString(NpcInteractState state) {
    switch (state) {
        case NpcInteractState::Idle: return "Idle";
        case NpcInteractState::ApproachNpc: return "ApproachNpc";
        case NpcInteractState::OpenDialogue: return "OpenDialogue";
        case NpcInteractState::SelectOption: return "SelectOption";
        case NpcInteractState::CloseDialogue: return "CloseDialogue";
        case NpcInteractState::Completed: return "Completed";
        case NpcInteractState::Failed: return "Failed";
        default: return "Unknown";
    }
}

enum class NpcInteractMode : uint8_t {
    TalkAndSkip = 0,        // Nói chuyện và bấm Space để skip dialogue (tiến độ quest)
    IdentifyAll = 1,        // The Hooded One: Chọn "Identify All Items" (0 vàng, 0 scroll)
    OpenVendor = 2,         // Mở giao diện buôn bán NPC (Vendor/Trade)
    OpenCurrencyExchange = 3,// Mở giao dịch tiền tệ Faustus Currency Exchange
    ClaimQuestReward = 4    // Nhận thưởng hoàn thành nhiệm vụ
};

inline const char* NpcInteractModeToString(NpcInteractMode mode) {
    switch (mode) {
        case NpcInteractMode::TalkAndSkip: return "TalkAndSkip";
        case NpcInteractMode::IdentifyAll: return "IdentifyAll";
        case NpcInteractMode::OpenVendor: return "OpenVendor";
        case NpcInteractMode::OpenCurrencyExchange: return "OpenCurrencyExchange";
        case NpcInteractMode::ClaimQuestReward: return "ClaimQuestReward";
        default: return "Unknown";
    }
}

enum class NpcRole : uint8_t {
    Generic = 0,
    Identifier = 1,         // The Hooded One
    CurrencyExchange = 2,   // Faustus (The Financier)
    Vendor = 3,             // Mua bán trang bị rác / Salvage
    QuestGiver = 4,         // Giao hoặc trả nhiệm vụ
    Master = 5              // Alva, Einhar, Kirac, Doryani...
};

inline NpcRole ClassifyNpcRole(const char* name) {
    if (!name || name[0] == '\0') return NpcRole::Generic;
    std::string lower(name);
    for (char& c : lower) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));

    if (lower.find("hooded") != std::string::npos || lower.find("hooded one") != std::string::npos) {
        return NpcRole::Identifier;
    }
    if (lower.find("faustus") != std::string::npos || lower.find("financier") != std::string::npos) {
        return NpcRole::CurrencyExchange;
    }
    if (lower.find("alva") != std::string::npos || lower.find("einhar") != std::string::npos ||
        lower.find("kirac") != std::string::npos || lower.find("doryani") != std::string::npos) {
        return NpcRole::Master;
    }
    if (lower.find("renly") != std::string::npos || lower.find("oswald") != std::string::npos ||
        lower.find("una") != std::string::npos || lower.find("finn") != std::string::npos ||
        lower.find("rory") != std::string::npos || lower.find("elias") != std::string::npos) {
        return NpcRole::QuestGiver;
    }
    return NpcRole::Generic;
}

struct NpcDialogueCoordinates {
    float refWidth = 1920.0f;
    float refHeight = 1080.0f;

    // Tọa độ Menu đối thoại (tham chiếu chuẩn 1080p)
    float dialogueMenuX = 960.0f;
    float dialogueMenuY = 420.0f;
    float dialogueOptionHeight = 36.0f;

    // Tọa độ tùy chọn "Identify All Items" của The Hooded One
    float identifyAllX = 960.0f;
    float identifyAllY = 456.0f;

    // Phím thoát đối thoại: Space (0x20) hoặc ESC (0x1B)
    uint8_t closeKey = VK_SPACE;
    uint8_t interactKey = 0; // Deprecated: POE2 KBM tương tác NPC bằng Click LMB, CẤM phím F (Skill 8)

    uint32_t stepDelayMs = 350;
    uint32_t jitterMs = 50;

    struct Point {
        float x = 0.0f;
        float y = 0.0f;
    };

    Point ScalePoint(float rawX, float rawY, float screenW, float screenH) const {
        float sx = (screenW > 0.0f) ? (screenW / refWidth) : 1.0f;
        float sy = (screenH > 0.0f) ? (screenH / refHeight) : 1.0f;
        return { rawX * sx, rawY * sy };
    }
};

class NpcInteractionHandler : public IActionHandler {
public:
    NpcInteractionHandler();

    // IActionHandler interface (BotBrain Arbiter P0/Doc 39)
    const char* Name() const override { return "NpcInteractionHandler"; }
    ActionProposal Propose(const TelemetryPacket& packet, uint64_t nowMs) override;
    bool Execute(const ActionProposal& chosen, const TelemetryPacket& packet, KMBoxNet& kmbox, uint64_t nowMs) override;

    bool LoadCoordinates(const std::string& tomlPath);
    bool StartInteract(const CommandPacket& cmd, uint64_t nowMs);
    bool StartInteract(uint32_t npcEntityId, NpcInteractMode mode, uint32_t optionIdx, uint64_t nowMs);
    void Reset();

    bool IsActive() const {
        return m_state != NpcInteractState::Idle &&
               m_state != NpcInteractState::Completed &&
               m_state != NpcInteractState::Failed;
    }

    NpcInteractState State() const { return m_state; }
    NpcInteractMode Mode() const { return m_mode; }
    uint32_t TargetNpcId() const { return m_targetNpcId; }
    const std::string& TargetNpcName() const { return m_targetNpcName; }
    uint32_t InteractionsCompletedCount() const { return m_interactionsCompleted; }
    const NpcDialogueCoordinates& Coordinates() const { return m_coords; }

    // Dành cho kiểm thử
    void SetStateForTest(NpcInteractState s, uint64_t lastMs) {
        m_state = s;
        m_lastStepMs = lastMs;
    }

private:
    bool AdvanceFsm(const TelemetryPacket& packet, KMBoxNet& kmbox, uint64_t nowMs);
    bool IsSafeZone(const TelemetryPacket& packet) const;
    int FindCandidateNpcIndex(const TelemetryPacket& packet) const;

    NpcInteractState m_state = NpcInteractState::Idle;
    NpcInteractMode m_mode = NpcInteractMode::TalkAndSkip;
    uint32_t m_targetNpcId = 0;
    std::string m_targetNpcName = "";
    uint32_t m_optionIndex = 0;

    uint64_t m_routineStartMs = 0;
    uint64_t m_lastStepMs = 0;
    uint32_t m_timeoutMs = 15000;
    uint32_t m_interactionsCompleted = 0;

    NpcDialogueCoordinates m_coords;
    HumanCurveGenerator m_curveGen;
};
