#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>

#include <cstdint>
#include <string>
#include <vector>
#include <unordered_map>
#include <memory>
#include <algorithm>
#include <cmath>

#include "combat/skills_table.hpp"

// ==========================================================
// AutoPOE2 Dedicated Skill Engine - Domain Models & Schemas
// (Architectural Blueprint: ARCH-SKILL-ENGINE-FLEXIBLE-2026-P6)
// ==========================================================

enum class AnimationPhase : uint8_t {
    Idle = 0,
    Windup = 1,
    Active = 2,
    Recovery = 3
};

inline const char* AnimationPhaseToString(AnimationPhase phase) {
    switch (phase) {
        case AnimationPhase::Idle: return "Idle";
        case AnimationPhase::Windup: return "Windup";
        case AnimationPhase::Active: return "Active";
        case AnimationPhase::Recovery: return "Recovery";
        default: return "Unknown";
    }
}

// 0. Trừu tượng hóa vai trò chiến thuật của kỹ năng (Skill Role Archetypes)
enum class SkillRole : uint8_t {
    BasicClear = 0,         // Chiêu dọn quái cơ bản (LMB: Mantra of Illusions, Whirling Assault)
    ComboBuilder = 1,       // Chiêu tích combo (Q: Tempest Flurry, Ice Strike)
    ComboSpender = 2,       // Chiêu xả combo / kết liễu diện rộng / đặt chuông (R: Tempest Bell)
    SustainedBuff = 3,      // Chiêu duy trì bão lôi / buff vũ khí (RMB: Charged Staff)
    GapCloser = 4,          // Chiêu áp sát & yểm bùa suy yếu (MMB: Wolf Leap)
    PreBuff = 5,            // Chiêu nạp nộ trước giao tranh (T: Bear Warcry)
    MobilityIframe = 6,     // Chiêu lăn né bất tử (Space: Dodge Roll)
    Skill8 = 7              // Phím F: Kỹ năng thứ 8 của người chơi (CẤM tương tác)
};

inline const char* SkillRoleToString(SkillRole role) {
    switch (role) {
        case SkillRole::BasicClear: return "BasicClear";
        case SkillRole::ComboBuilder: return "ComboBuilder";
        case SkillRole::ComboSpender: return "ComboSpender";
        case SkillRole::SustainedBuff: return "SustainedBuff";
        case SkillRole::GapCloser: return "GapCloser";
        case SkillRole::PreBuff: return "PreBuff";
        case SkillRole::MobilityIframe: return "MobilityIframe";
        case SkillRole::Skill8: return "Skill8";
        default: return "Unknown";
    }
}

// 1. Snapshot sinh mệnh và tài nguyên của nhân vật
struct PlayerVitalsSnapshot {
    int32_t curLife = 0;
    int32_t maxLife = 0;
    int32_t curES = 0;
    int32_t maxES = 0;
    int32_t curWard = 0;
    int32_t maxWard = 0;
    int32_t curMana = 0;
    int32_t maxMana = 0;
    int32_t curSpirit = 0;
    int32_t maxSpirit = 0;
    int32_t curRage = 0;
    int32_t maxRage = 100;
    int32_t comboPoints = 0;
    int32_t staffCharges = 0;

    float LifePct() const { return maxLife > 0 ? (float)curLife / (float)maxLife : 0.0f; }
    float EsPct() const { return maxES > 0 ? (float)curES / (float)maxES : 0.0f; }
    float ManaPct() const { return maxMana > 0 ? (float)curMana / (float)maxMana : 0.0f; }
};

// 2. Ngữ cảnh mục tiêu chiến đấu (Target Context)
struct TargetContext {
    uint32_t id = 0;
    uint8_t rarity = 0; // 0=normal, 1=magic, 2=rare, 3=unique/boss
    float distance = 9999.0f;
    float posX = 0.0f;
    float posY = 0.0f;
    float hpPct = 1.0f;
    uint16_t staggerPct = 0; // 0..10000 (8000 = 80%)
    bool hasMarkedDebuff = false;
    uint64_t markExpiryMs = 0;

    bool IsMarked(uint64_t nowMs) const {
        return hasMarkedDebuff && (markExpiryMs == 0 || nowMs < markExpiryMs);
    }
};

// 3. Ngữ cảnh đồng đội và vật triệu hồi (Party & Minions)
struct PartyContext {
    bool hasDetermination = false;
    bool hasGrace = false;
    bool hasHaste = false;
    uint32_t minionCount = 0;
};

// 4. Bảng thuộc tính trang bị & Keystone (Gear Modifiers Cache)
struct GearModifiers {
    bool isChaosInoculation = false;
    float attackSpeedMultiplier = 1.0f;
    float castSpeedMultiplier = 1.0f;
    float cooldownRecoveryMultiplier = 1.0f;
};

// 5. Máy trạng thái hoạt ảnh kỹ năng (Animation Lock State)
struct AnimationState {
    AnimationPhase phase = AnimationPhase::Idle;
    uint8_t currentSkillVk = 0;
    uint64_t phaseStartMs = 0;
    uint32_t windupDurationMs = 0;
    uint32_t activeDurationMs = 0;
    uint32_t recoveryDurationMs = 0;
    bool canEmergencyCancel = true;

    bool IsLocked(uint64_t nowMs) const {
        if (phase == AnimationPhase::Idle) return false;
        uint64_t elapsed = (nowMs >= phaseStartMs) ? (nowMs - phaseStartMs) : 0;
        if (phase == AnimationPhase::Windup) {
            return elapsed < windupDurationMs;
        }
        if (phase == AnimationPhase::Active) {
            return elapsed < activeDurationMs;
        }
        if (phase == AnimationPhase::Recovery) {
            return elapsed < recoveryDurationMs;
        }
        return false;
    }

    void UpdatePhase(uint64_t nowMs) {
        if (phase == AnimationPhase::Idle) return;
        uint64_t elapsed = (nowMs >= phaseStartMs) ? (nowMs - phaseStartMs) : 0;
        if (phase == AnimationPhase::Windup && elapsed >= windupDurationMs) {
            phase = AnimationPhase::Active;
            phaseStartMs = nowMs;
        } else if (phase == AnimationPhase::Active && elapsed >= activeDurationMs) {
            phase = AnimationPhase::Recovery;
            phaseStartMs = nowMs;
        } else if (phase == AnimationPhase::Recovery && elapsed >= recoveryDurationMs) {
            phase = AnimationPhase::Idle;
            currentSkillVk = 0;
            phaseStartMs = 0;
        }
    }
};

// 6. Ngữ cảnh môi trường thực địa (Environment Context)
struct EnvironmentContext {
    bool hasFieldBell = false;
    float bellDistance = 9999.0f;
    float bellPosX = 0.0f;
    float bellPosY = 0.0f;
    uint64_t bellExpiryMs = 0;

    bool IsBellActive(uint64_t nowMs) const {
        return hasFieldBell && (bellExpiryMs == 0 || nowMs < bellExpiryMs);
    }
};

// 7. Hợp nhất ngữ cảnh chiến đấu (Unified Combat Context)
struct CombatContext {
    PlayerVitalsSnapshot vitals;
    TargetContext target;
    PartyContext party;
    GearModifiers gear;
    AnimationState anim;
    EnvironmentContext env;
    uint32_t nearbyEnemyCount = 0;
};

// 8. Định nghĩa điều kiện tiên quyết (Condition Engine)
enum class ConditionType : uint8_t {
    MinResource = 0,
    MaxResource = 1,
    MinDistance = 2,
    MaxDistance = 3,
    TargetRarityMin = 4,
    TargetDebuffRequired = 5,
    TargetDebuffAbsent = 6,
    MinComboPoints = 7,
    MaxComboPoints = 8,
    TrackerExact = 9,
    FieldEntityNear = 10,
    MinionCountMin = 11,
    MinLifePct = 12,
    MaxLifePct = 13,
    MinEsPct = 14,
    MaxEsPct = 15,
    MinManaPct = 16,
    MaxManaPct = 17,
    MinRage = 18,
    MaxRage = 19
};

struct ConditionRule {
    ConditionType type = ConditionType::MinDistance;
    std::string resourceName; // e.g. "rage", "combo_points"
    int64_t intValue = 0;
    float floatValue = 0.0f;

    bool Evaluate(const CombatContext& ctx, const std::unordered_map<std::string, int64_t>& trackers, uint64_t nowMs) const {
        switch (type) {
            case ConditionType::MinDistance:
                return ctx.target.distance >= floatValue;
            case ConditionType::MaxDistance:
                return ctx.target.distance <= floatValue;
            case ConditionType::TargetRarityMin:
                return ctx.target.rarity >= (uint8_t)intValue;
            case ConditionType::TargetDebuffRequired:
                return ctx.target.IsMarked(nowMs);
            case ConditionType::TargetDebuffAbsent:
                return !ctx.target.IsMarked(nowMs);
            case ConditionType::MinComboPoints: {
                int64_t curCombo = ctx.vitals.comboPoints;
                auto it = trackers.find("combo_points");
                if (it != trackers.end()) curCombo = it->second;
                return curCombo >= intValue;
            }
            case ConditionType::MaxComboPoints: {
                int64_t curCombo = ctx.vitals.comboPoints;
                auto it = trackers.find("combo_points");
                if (it != trackers.end()) curCombo = it->second;
                return curCombo <= intValue;
            }
            case ConditionType::TrackerExact: {
                auto it = trackers.find(resourceName);
                int64_t cur = (it != trackers.end()) ? it->second : 0;
                return cur == intValue;
            }
            case ConditionType::FieldEntityNear:
                return ctx.env.IsBellActive(nowMs) && ctx.env.bellDistance <= floatValue;
            case ConditionType::MinionCountMin:
                return ctx.party.minionCount >= (uint32_t)intValue;
            case ConditionType::MinLifePct:
                return ctx.vitals.LifePct() >= floatValue;
            case ConditionType::MaxLifePct:
                return ctx.vitals.LifePct() <= floatValue;
            case ConditionType::MinEsPct:
                return ctx.vitals.EsPct() >= floatValue;
            case ConditionType::MaxEsPct:
                return ctx.vitals.EsPct() <= floatValue;
            case ConditionType::MinManaPct:
                return ctx.vitals.ManaPct() >= floatValue;
            case ConditionType::MaxManaPct:
                return ctx.vitals.ManaPct() <= floatValue;
            case ConditionType::MinRage:
                return ctx.vitals.curRage >= intValue;
            case ConditionType::MaxRage:
                return ctx.vitals.curRage <= intValue;
            default:
                return true;
        }
    }
};

// 9. Định nghĩa hiệu ứng phụ sau khi thi triển (Skill Effects)
enum class EffectType : uint8_t {
    IncrementTracker = 0,
    ResetTracker = 1,
    SetTracker = 2,
    ApplyTargetDebuff = 3,
    SpawnFieldEntity = 4,
    GrantBuff = 5,
    GrantRage = 6
};

struct SkillEffect {
    EffectType type = EffectType::IncrementTracker;
    std::string targetName; // e.g. "combo_points", "Marked_Vulnerability", "ResonanceBell"
    int64_t value = 0;
    uint32_t durationMs = 0;
};

// 10. Định nghĩa kỹ năng mở rộng (Flexible Skill)
struct FlexibleSkill {
    std::string id;
    std::string name;
    std::string assetName;
    std::string keyStr;
    uint8_t vkCode = 0;
    SkillKind kind = SkillKind::Attack;
    SkillRole role = SkillRole::BasicClear;

    uint32_t basePriority = 1;
    uint32_t cooldownMs = 0;
    uint32_t windupMs = 150;
    uint32_t activeMs = 100;
    uint32_t recoveryMs = 150;

    float minDistance = 0.0f;
    float maxDistance = 300.0f;
    bool maintain = false;

    // Tương tác chéo & Synergy
    float targetMarkedMultiplier = 1.0f; // Tăng ưu tiên khi target bị mark
    float lowEsPriorityBonus = 0.0f;

    std::vector<ConditionRule> preconditions;
    std::vector<SkillEffect> effects;

    // Runtime state
    uint64_t lastCastMs = 0;
    uint64_t activeBuffUntilMs = 0;

    bool IsCooldownReady(uint64_t nowMs, float cdrMult = 1.0f) const {
        if (lastCastMs == 0 || cooldownMs == 0) return true;
        uint32_t effCooldown = (cdrMult > 0.01f) ? (uint32_t)(cooldownMs / cdrMult) : cooldownMs;
        return (nowMs >= lastCastMs + effCooldown);
    }

    bool ArePreconditionsMet(const CombatContext& ctx, const std::unordered_map<std::string, int64_t>& trackers, uint64_t nowMs) const {
        // Kiểm tra cooldown
        if (!IsCooldownReady(nowMs, ctx.gear.cooldownRecoveryMultiplier)) {
            return false;
        }

        // Kiểm tra cự ly cơ bản nếu là đòn đánh
        if (kind == SkillKind::Attack) {
            if (ctx.target.distance < minDistance || ctx.target.distance > maxDistance) {
                return false;
            }
        }

        // Kiểm tra toàn bộ preconditions
        for (const auto& cond : preconditions) {
            if (!cond.Evaluate(ctx, trackers, nowMs)) {
                return false;
            }
        }
        return true;
    }

    uint32_t CalculateEffectivePriority(const CombatContext& ctx, uint64_t nowMs) const {
        float prio = (float)basePriority;
        if (ctx.target.IsMarked(nowMs) && targetMarkedMultiplier > 1.0f) {
            // Trong hệ thống xếp hạng (Rank 1 là cao nhất), multiplier > 1.0 giúp tăng bậc ưu tiên (giảm số rank)
            prio = (std::max)(1.0f, std::round(prio / targetMarkedMultiplier));
        }
        return (uint32_t)prio;
    }
};

// 11. Quyết định xuất chiêu từ Skill Engine
enum class SkillDecisionKind : uint8_t {
    Idle = 0,
    CastSkill = 1,
    EmergencyCancel = 2,
    WaitAnimation = 3
};

struct SkillDecision {
    SkillDecisionKind kind = SkillDecisionKind::Idle;
    uint8_t vkCode = 0;
    std::string skillName;
    float targetX = 0.0f;
    float targetY = 0.0f;
    uint32_t priority = 0;
    std::string reason;
};
