#include <spdlog/spdlog.h>
#include <algorithm>
#include <cctype>
#include "./symbol.hpp"
#include "../../protocol/transform/facade.hpp"
#include "../../service/document.hpp"
#include "../../service/symbol.hpp"

namespace lsp::provider::workspace
{
    std::string Symbol::GetMethod() const
    {
        return "workspace/symbol";
    }

    std::string Symbol::GetProviderName() const
    {
        return "WorkSpaceSymbol";
    }

    std::string Symbol::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
    {
        spdlog::debug("WorkspaceSymbolProvider: Providing response for method {}", request.method);

        if (!request.params.has_value())
        {
            spdlog::warn("{}: Missing params in request", GetProviderName());
            return BuildErrorResponseMessage(request, protocol::ErrorCodes::InvalidParams, "Missing params");
        }

        protocol::WorkspaceSymbolParams params =
            transform::As<protocol::WorkspaceSymbolParams>(request.params.value());

        auto symbols = BuildSymbolResponse(params, context);

        protocol::ResponseMessage response;
        response.id = request.id;
        response.result = transform::LSPAny(symbols);

        std::optional<std::string> json = transform::Serialize(response);
        if (!json.has_value())
            return BuildErrorResponseMessage(request, protocol::ErrorCodes::InternalError, "Failed to serialize response");
        return json.value();
    }

    std::vector<protocol::SymbolInformation> Symbol::BuildSymbolResponse(const protocol::WorkspaceSymbolParams& params, ExecutionContext& context)
    {
        spdlog::trace("{}: Searching for symbols matching '{}'", GetProviderName(), params.query);

        auto symbols = SearchSymbols(params.query, context);

        // 按匹配分数排序
        std::sort(symbols.begin(), symbols.end(), [&params](const protocol::SymbolInformation& a, const protocol::SymbolInformation& b) {
            // 可以实现更复杂的排序逻辑
            return a.name < b.name;
        });

        // 限制返回数量（避免返回太多结果）
        const size_t max_results = 100;
        if (symbols.size() > max_results)
        {
            symbols.resize(max_results);
            spdlog::debug("{}: Limited results to {} symbols", GetProviderName(), max_results);
        }

        spdlog::info("{}: Found {} symbols matching '{}'", GetProviderName(), symbols.size(), params.query);

        return symbols;
    }

    std::vector<protocol::SymbolInformation> Symbol::SearchSymbols(
        const std::string& query,
        ExecutionContext& context)
    {
        std::vector<protocol::SymbolInformation> results;

        // 从容器获取服务
        auto& document_service = context.GetService<service::Document>();
        auto& symbol_service = context.GetService<service::Symbol>();

        // 获取所有打开的文档
        auto document_uris = document_service.GetAllDocumentUris();

        for (const auto& uri : document_uris)
        {
            // 获取文档符号
            auto doc_symbols = symbol_service.GetDocumentSymbols(uri);

            // 递归转换并过滤符号
            for (const auto& symbol : doc_symbols)
            {
                ConvertToSymbolInformation(symbol, uri, query, results);
            }
        }

        return results;
    }

    void Symbol::ConvertToSymbolInformation(
        const protocol::DocumentSymbol& doc_symbol,
        const protocol::DocumentUri& uri,
        const std::string& query,
        std::vector<protocol::SymbolInformation>& results,
        const std::string& container_name)
    {
        // 检查是否匹配查询
        if (MatchesQuery(doc_symbol.name, query))
        {
            protocol::SymbolInformation info;
            info.name = doc_symbol.name;
            info.kind = doc_symbol.kind;
            info.location.uri = uri;
            info.location.range = doc_symbol.range;

            // 设置容器名称
            if (!container_name.empty())
            {
                info.containerName = container_name;
            }

            results.push_back(info);
        }

        // 递归处理子符号
        std::string new_container = container_name.empty() ?  doc_symbol.name : container_name + "." + doc_symbol.name;

        for (const auto& child : doc_symbol.children.value())
        {
            ConvertToSymbolInformation(child, uri, query, results, new_container);
        }
    }

    bool Symbol::MatchesQuery(const std::string& symbol_name, const std::string& query)
    {
        // 空查询匹配所有
        if (query.empty())
            return true;

        // 转换为小写进行不区分大小写的匹配
        std::string lower_symbol = symbol_name;
        std::string lower_query = query;
        std::transform(lower_symbol.begin(), lower_symbol.end(), lower_symbol.begin(), ::tolower);
        std::transform(lower_query.begin(), lower_query.end(), lower_query.begin(), ::tolower);

        // 1. 精确匹配
        if (lower_symbol == lower_query)
            return true;

        // 2. 前缀匹配
        if (lower_symbol.find(lower_query) == 0)
            return true;

        // 3. 包含匹配
        if (lower_symbol.find(lower_query) != std::string::npos)
            return true;

        // 4. 模糊匹配（驼峰匹配）
        if (FuzzyMatch(query, symbol_name))
            return true;

        return false;
    }

    bool Symbol::FuzzyMatch(const std::string& pattern, const std::string& text)
    {
        // 实现驼峰匹配
        // 例如 "gS" 匹配 "getString"
        size_t pattern_idx = 0;
        size_t text_idx = 0;

        while (pattern_idx < pattern.length() && text_idx < text.length())
        {
            char p = pattern[pattern_idx];

            // 查找下一个匹配字符
            bool found = false;
            while (text_idx < text.length())
            {
                char t = text[text_idx];

                // 不区分大小写匹配
                if (std::tolower(p) == std::tolower(t))
                {
                    found = true;
                    text_idx++;
                    break;
                }

                // 如果模式字符是大写，只在大写字母位置匹配
                if (std::isupper(p) && !std::isupper(t))
                {
                    text_idx++;
                    continue;
                }

                text_idx++;
            }

            if (!found)
                return false;

            pattern_idx++;
        }

        return pattern_idx == pattern.length();
    }

    int Symbol::CalculateScore(const std::string& symbol_name, const std::string& query)
    {
        int score = 0;

        // 精确匹配得分最高
        if (symbol_name == query)
            return 1000;

        // 前缀匹配得分次高
        if (symbol_name.find(query) == 0)
            return 900;

        // 不区分大小写的前缀匹配
        std::string lower_symbol = symbol_name;
        std::string lower_query = query;
        std::transform(lower_symbol.begin(), lower_symbol.end(), lower_symbol.begin(), ::tolower);
        std::transform(lower_query.begin(), lower_query.end(), lower_query.begin(), ::tolower);

        if (lower_symbol.find(lower_query) == 0)
            return 800;

        // 包含匹配
        size_t pos = lower_symbol.find(lower_query);
        if (pos != std::string::npos)
        {
            // 越靠前得分越高
            score = 700 - static_cast<int>(pos * 10);
        }

        // 模糊匹配得分最低
        if (FuzzyMatch(query, symbol_name))
        {
            score = std::max(score, 500);
        }

        return score;
    }
}
