// ==========================================================
// item_parser.cpp - Fast C++23 Native POE2 Item & Waystone Parser
// Poe2VisualTool v2.0.0 (100% C++23 Native Fusion)
// Pure C++23 string_view parser — Zero Regex Overhead, Zero Allocations
// ==========================================================

#include "inspector/item_parser.hpp"
#include "inspector/waystone_rules.hpp"

#include <algorithm>
#include <cctype>
#include <sstream>

namespace inspector {

namespace {

inline std::string_view Trim(std::string_view s) {
    while (!s.empty() && (static_cast<unsigned char>(s.front()) <= ' ')) {
        s.remove_prefix(1);
    }
    while (!s.empty() && (static_cast<unsigned char>(s.back()) <= ' ')) {
        s.remove_suffix(1);
    }
    return s;
}

inline bool ContainsIgnoreCase(std::string_view haystack, std::string_view needle) noexcept {
    if (needle.empty()) return true;
    if (haystack.size() < needle.size()) return false;
    auto it = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(),
        [](char h, char n) noexcept {
            return std::tolower(static_cast<unsigned char>(h)) == std::tolower(static_cast<unsigned char>(n));
        });
    return it != haystack.end();
}

inline int SafeParseInt(std::string_view s) noexcept {
    int64_t val = 0;
    bool found = false;
    for (char c : s) {
        if (c >= '0' && c <= '9') {
            val = val * 10 + (c - '0');
            if (val > INT_MAX) return INT_MAX;
            found = true;
        } else if (found) {
            break;
        }
    }
    return found ? static_cast<int>(val) : 0;
}

inline std::vector<std::string_view> SplitLines(std::string_view text) {
    std::vector<std::string_view> lines;
    size_t start = 0;
    while (start < text.size()) {
        size_t end = text.find('\n', start);
        if (end == std::string_view::npos) {
            std::string_view l = Trim(text.substr(start));
            if (!l.empty()) lines.push_back(l);
            break;
        }
        std::string_view l = Trim(text.substr(start, end - start));
        if (!l.empty()) lines.push_back(l);
        start = end + 1;
    }
    return lines;
}

inline std::vector<std::vector<std::string_view>> SplitSections(std::string_view text) {
    std::vector<std::vector<std::string_view>> sections;
    std::vector<std::string_view> current;
    auto lines = SplitLines(text);

    for (auto line : lines) {
        if (line.rfind("--------", 0) == 0) {
            if (!current.empty()) {
                sections.push_back(std::move(current));
                current.clear();
            }
        } else if (!line.empty()) {
            current.push_back(line);
        }
    }
    if (!current.empty()) {
        sections.push_back(std::move(current));
    }
    return sections;
}

} // namespace

ItemRarity ItemParser::ParseRarity(std::string_view rarityStr) {
    if (ContainsIgnoreCase(rarityStr, "magic")) return ItemRarity::Magic;
    if (ContainsIgnoreCase(rarityStr, "rare")) return ItemRarity::Rare;
    if (ContainsIgnoreCase(rarityStr, "unique")) return ItemRarity::Unique;
    if (ContainsIgnoreCase(rarityStr, "currency")) return ItemRarity::Currency;
    if (ContainsIgnoreCase(rarityStr, "gem")) return ItemRarity::Gem;
    return ItemRarity::Normal;
}

ItemCategory ItemParser::DeduceCategory(std::string_view itemClass, std::string_view name) {
    if (ContainsIgnoreCase(itemClass, "waystone") || ContainsIgnoreCase(name, "waystone")) {
        return ItemCategory::Waystone;
    }
    if (ContainsIgnoreCase(itemClass, "body armour")) return ItemCategory::BodyArmour;
    if (ContainsIgnoreCase(itemClass, "boots")) return ItemCategory::Boots;
    if (ContainsIgnoreCase(itemClass, "gloves")) return ItemCategory::Gloves;
    if (ContainsIgnoreCase(itemClass, "helmet")) return ItemCategory::Helmet;
    if (ContainsIgnoreCase(itemClass, "shield")) return ItemCategory::Shield;
    if (ContainsIgnoreCase(itemClass, "ring")) return ItemCategory::Ring;
    if (ContainsIgnoreCase(itemClass, "amulet")) return ItemCategory::Amulet;
    if (ContainsIgnoreCase(itemClass, "belt")) return ItemCategory::Belt;
    if (ContainsIgnoreCase(itemClass, "jewel")) return ItemCategory::Jewel;
    if (ContainsIgnoreCase(itemClass, "charm")) return ItemCategory::Charm;
    if (ContainsIgnoreCase(itemClass, "flask")) return ItemCategory::Flask;
    if (ContainsIgnoreCase(itemClass, "quiver")) return ItemCategory::Quiver;
    if (ContainsIgnoreCase(itemClass, "bow") || ContainsIgnoreCase(itemClass, "wand") ||
        ContainsIgnoreCase(itemClass, "staff") || ContainsIgnoreCase(itemClass, "sword") ||
        ContainsIgnoreCase(itemClass, "axe") || ContainsIgnoreCase(itemClass, "mace") ||
        ContainsIgnoreCase(itemClass, "dagger") || ContainsIgnoreCase(itemClass, "crossbow") ||
        ContainsIgnoreCase(itemClass, "flail") || ContainsIgnoreCase(itemClass, "quarterstaff") ||
        ContainsIgnoreCase(itemClass, "spear")) {
        return ItemCategory::Weapon;
    }
    if (ContainsIgnoreCase(itemClass, "currency")) return ItemCategory::Currency;

    return ItemCategory::Other;
}

bool ItemParser::IsPrefix(std::string_view modText) {
    // Máu & Mana & Spirit
    if (ContainsIgnoreCase(modText, "to maximum life") ||
        ContainsIgnoreCase(modText, "increased maximum life") ||
        ContainsIgnoreCase(modText, "to maximum mana") ||
        ContainsIgnoreCase(modText, "increased maximum mana") ||
        ContainsIgnoreCase(modText, "to maximum spirit")) {
        return true;
    }

    // Giáp, Né tránh, Khiên năng lượng (Flat & %)
    if (ContainsIgnoreCase(modText, "to armour") ||
        ContainsIgnoreCase(modText, "increased armour") ||
        ContainsIgnoreCase(modText, "to evasion rating") ||
        ContainsIgnoreCase(modText, "increased evasion rating") ||
        ContainsIgnoreCase(modText, "to energy shield") ||
        ContainsIgnoreCase(modText, "increased energy shield")) {
        return true;
    }

    // Sát thương cộng thêm (Adds X to Y Damage)
    if (ContainsIgnoreCase(modText, "adds ") && ContainsIgnoreCase(modText, "damage")) {
        return true;
    }

    // Tăng % Sát thương (Physical, Spell, Elemental)
    if (ContainsIgnoreCase(modText, "increased physical damage") ||
        ContainsIgnoreCase(modText, "increased spell damage") ||
        ContainsIgnoreCase(modText, "increased elemental damage")) {
        return true;
    }

    // Level of Gems
    if (ContainsIgnoreCase(modText, "to level of") && ContainsIgnoreCase(modText, "gems")) {
        return true;
    }

    // Movement Speed on Boots
    if (ContainsIgnoreCase(modText, "increased movement speed")) {
        return true;
    }

    // Leech & Flask recovery
    if (ContainsIgnoreCase(modText, "leeched as life") ||
        ContainsIgnoreCase(modText, "leeched as mana") ||
        ContainsIgnoreCase(modText, "recovered")) {
        return true;
    }

    return false;
}

bool ItemParser::IsSuffix(std::string_view modText) {
    // Resistances
    if (ContainsIgnoreCase(modText, "resistance") ||
        ContainsIgnoreCase(modText, "resistances")) {
        return true;
    }

    // Attributes (Strength, Dexterity, Intelligence)
    if (ContainsIgnoreCase(modText, "to strength") ||
        ContainsIgnoreCase(modText, "to dexterity") ||
        ContainsIgnoreCase(modText, "to intelligence") ||
        ContainsIgnoreCase(modText, "to all attributes")) {
        return true;
    }

    // Critical Strike (Chance & Multiplier)
    if (ContainsIgnoreCase(modText, "critical strike")) {
        return true;
    }

    // Attack Speed & Cast Speed
    if (ContainsIgnoreCase(modText, "attack speed") ||
        ContainsIgnoreCase(modText, "cast speed")) {
        return true;
    }

    // Accuracy Rating
    if (ContainsIgnoreCase(modText, "accuracy rating")) {
        return true;
    }

    // Spell Suppression
    if (ContainsIgnoreCase(modText, "chance to suppress spell damage")) {
        return true;
    }

    // Regeneration
    if (ContainsIgnoreCase(modText, "regenerate") ||
        ContainsIgnoreCase(modText, "mana regeneration rate")) {
        return true;
    }

    // Item Rarity
    if (ContainsIgnoreCase(modText, "rarity of items found")) {
        return true;
    }

    return false;
}

AffixType ItemParser::ClassifyAffix(std::string_view modText) {
    if (IsPrefix(modText)) return AffixType::Prefix;
    if (IsSuffix(modText)) return AffixType::Suffix;
    return AffixType::Unknown;
}

ItemInspectionReport ItemParser::Parse(std::string_view clipboardText) {
    ItemInspectionReport report;
    auto sections = SplitSections(clipboardText);
    if (sections.empty()) {
        return report;
    }

    int detectedPrefixes = 0;
    int detectedSuffixes = 0;
    int orderCounter = 0;

    // Duyệt qua từng section
    for (size_t secIdx = 0; secIdx < sections.size(); ++secIdx) {
        const auto& sec = sections[secIdx];
        if (sec.empty()) continue;

        // Section 0: Chứa Item Class, Rarity, Tên, Base Type
        if (secIdx == 0) {
            size_t nameLineIdx = 0;
            for (size_t i = 0; i < sec.size(); ++i) {
                std::string_view line = sec[i];
                if (line.starts_with("Item Class:")) {
                    report.itemClass = std::string(Trim(line.substr(11)));
                } else if (line.starts_with("Rarity:")) {
                    report.rarity = ParseRarity(Trim(line.substr(7)));
                    nameLineIdx = i + 1;
                }
            }

            if (nameLineIdx < sec.size()) {
                report.itemName = std::string(sec[nameLineIdx]);
                if (nameLineIdx + 1 < sec.size() &&
                    (report.rarity == ItemRarity::Rare || report.rarity == ItemRarity::Unique)) {
                    report.baseType = std::string(sec[nameLineIdx + 1]);
                } else {
                    report.baseType = report.itemName;
                }
            }
            report.category = DeduceCategory(report.itemClass, report.itemName);
            continue;
        }

        // Kiểm tra xem section có phải là properties / requirements / sockets / ilvl không
        bool isPropertyOrReq = false;
        for (auto line : sec) {
            if (line.starts_with("Quality:")) {
                report.quality = SafeParseInt(line);
                isPropertyOrReq = true;
            } else if (line.starts_with("Item Level:")) {
                report.itemLevel = SafeParseInt(line);
                isPropertyOrReq = true;
            } else if (line.starts_with("Sockets:")) {
                report.sockets = std::string(Trim(line.substr(8)));
                isPropertyOrReq = true;
            } else if (line.starts_with("Requirements:") ||
                       line.starts_with("Level:") ||
                       line.starts_with("Str:") ||
                       line.starts_with("Dex:") ||
                       line.starts_with("Int:") ||
                       line.starts_with("Waystone Tier:") ||
                       line.starts_with("Corrupted")) {
                if (line.starts_with("Corrupted")) report.isCorrupted = true;
                isPropertyOrReq = true;
            }
        }

        if (isPropertyOrReq) {
            for (auto l : sec) {
                report.properties.push_back(std::string(l));
            }
            continue;
        }

        // Section này chứa modifiers (Implicit hoặc Explicit)
        std::optional<AffixType> currentAffixTag;
        std::optional<int> currentTier;
        std::string currentCategory;

        for (auto line : sec) {
            // Nhận diện Advanced Mod tags: { Prefix Modifier ... (Tier: X) }
            if (line.starts_with("{") && line.ends_with("}")) {
                if (ContainsIgnoreCase(line, "prefix modifier")) currentAffixTag = AffixType::Prefix;
                else if (ContainsIgnoreCase(line, "suffix modifier")) currentAffixTag = AffixType::Suffix;
                else if (ContainsIgnoreCase(line, "implicit modifier")) currentAffixTag = AffixType::Implicit;

                auto it = std::search(line.begin(), line.end(), "(tier: ", "(tier: " + 7,
                    [](char a, char b) noexcept {
                        return std::tolower(static_cast<unsigned char>(a)) == std::tolower(static_cast<unsigned char>(b));
                    });
                if (it != line.end()) {
                    size_t off = static_cast<size_t>(std::distance(line.begin(), it)) + 7;
                    currentTier = SafeParseInt(line.substr(off));
                }
                continue;
            }

            // Dòng modifier thực tế
            std::string lineStr(line);
            InspectionMod mod;
            mod.text = lineStr;
            mod.originalOrder = ++orderCounter;

            if (currentAffixTag.has_value()) {
                mod.affixType = *currentAffixTag;
                mod.category = currentCategory;
                mod.tier = currentTier.value_or(0);
                currentAffixTag.reset();
                currentTier.reset();
                currentCategory.clear();
            } else {
                mod.affixType = ClassifyAffix(line);
            }

            if (mod.affixType == AffixType::Prefix) detectedPrefixes++;
            else if (mod.affixType == AffixType::Suffix) detectedSuffixes++;

            // Đánh giá nguy hiểm / đặc tính qua WaystoneRules
            ModEvaluation eval = WaystoneRules::EvaluateMod(line);
            mod.severity = eval.severity;
            mod.colorHex = eval.colorHex;
            mod.description = eval.description;
            if (mod.category.empty()) mod.category = eval.category;

            if (eval.severity == ModSeverity::Brick) {
                report.isBrick = true;
                report.safetyScore -= eval.scorePenalty;
                report.redMods.push_back(lineStr);
            } else if (eval.severity == ModSeverity::Dangerous) {
                report.safetyScore -= eval.scorePenalty;
                report.redMods.push_back(lineStr);
            } else if (eval.severity == ModSeverity::Reward) {
                report.greenMods.push_back(lineStr);
                report.qualityScore += 25;
            } else {
                report.neutralMods.push_back(lineStr);
            }

            report.rawMods.push_back(mod);
            report.orderedModifiers.push_back(mod);
        }
    }

    report.safetyScore = std::clamp(report.safetyScore, 0, 100);

    // Tính toán số lượng Open Affixes theo chuẩn POE2
    if (report.rarity == ItemRarity::Magic) {
        report.maxPrefixes = 1;
        report.maxSuffixes = 1;
    } else if (report.rarity == ItemRarity::Rare) {
        report.maxPrefixes = 3;
        report.maxSuffixes = 3;
    }

    if (report.maxPrefixes > 0 || report.maxSuffixes > 0) {
        report.openPrefixes = (std::max)(0, report.maxPrefixes - detectedPrefixes);
        report.openSuffixes = (std::max)(0, report.maxSuffixes - detectedSuffixes);
    }

    // Tóm tắt kết quả
    if (report.category == ItemCategory::Waystone) {
        if (report.isBrick) {
            report.summary = "🛑 MAP BRICK! (Tử trận chắc chắn - Không nên chạy)";
        } else if (report.safetyScore < 70) {
            report.summary = "⚠️ NGUY HIỂM CAO! Cần cẩn trọng khi đi map này.";
        } else {
            report.summary = "✅ AN TOÀN! Có thể chạy map thuận lợi.";
        }
    } else {
        std::ostringstream oss;
        oss << "Open Affixes: " << report.openPrefixes << "P / " << report.openSuffixes << "S";
        if (report.openPrefixes > 0 || report.openSuffixes > 0) {
            oss << " (Tiềm năng chế đồ / đập Rune)";
        }
        report.summary = oss.str();
    }

    return report;
}

} // namespace inspector
