#include <spdlog/spdlog.h>
#include "./completion_provider.hpp"
#include "../../protocol/transform/facade.hpp"

namespace lsp::providers::text_document
{
    std::string CompletionProvider::GetMethod() const
    {
        return "textDocument/completion";
    }

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

    std::string CompletionProvider::ProvideResponse(const protocol::RequestMessage& request, ProviderContext& context)
    {
        static_cast<void>(context);
        spdlog::debug("CompletionProvider: Providing response for method {}", request.method);

        try {
            // 验证请求是否包含参数
            if (!request.params.has_value())
            {
                spdlog::warn("{}: Missing params in request", GetProviderName());
                return BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Missing params");
            }

            // 从 variant 中提取参数
            protocol::CompletionParams completion_params = transform::As<protocol::CompletionParams>(request.params.value());
            protocol::CompletionList completion_list = BuildCompletionResponse(completion_params);

            // 构建响应消息
            protocol::ResponseMessage response;
            response.id = request.id;
            response.result = transform::LSPAny(completion_list);

            std::string json;
            auto ec = glz::write_json(response, json);
            if (ec) {
                spdlog::error("{}: Failed to serialize response: {}", GetProviderName(), glz::format_error(ec, json));
                return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Failed to serialize response");
            }

            return json;

        } catch (const transform::ConversionError& e) {
            spdlog::error("{}: Failed to convert params: {}", GetProviderName(), e.what());
            return BuildErrorResponseMessage(request, protocol::ErrorCode::kInvalidParams, "Invalid completion params");
        } catch (const std::exception& e) {
            spdlog::error("{}: Unexpected error: {}", GetProviderName(), e.what());
            return BuildErrorResponseMessage(request, protocol::ErrorCode::kInternalError, "Internal error");
        }
    }


    protocol::CompletionList CompletionProvider::BuildCompletionResponse(const protocol::CompletionParams& params)
    {
        spdlog::trace("{}: Processing completion request for URI='{}', Position=({}, {})",
                     GetProviderName(),
                     params.textDocument.uri,
                     params.position.line,
                     params.position.character);

        // 获取补全前缀
        std::string prefix = ExtractPrefix(params.textDocument, params.position);

        // 如果提供了 context，可以使用其中的信息
        if (params.context.has_value())
        {
            spdlog::trace("{}: Trigger kind: {}", GetProviderName(), static_cast<int>(params.context->triggerKind));
            if (params.context->triggerCharacter.has_value())
                spdlog::trace("{}: Trigger character: '{}'", GetProviderName(), params.context->triggerCharacter.value());
        }

        // 收集所有补全项
        std::vector<protocol::CompletionItem> allItems;

        // 添加关键字补全
        auto keywordItems = ProvideKeywordCompletions(prefix);
        allItems.insert(allItems.end(), keywordItems.begin(), keywordItems.end());

        // 添加上下文相关补全
        auto contextualItems = ProvideContextualCompletions(params.textDocument, params.position, prefix);
        allItems.insert(allItems.end(), contextualItems.begin(), contextualItems.end());

        // 构建补全列表
        protocol::CompletionList result;
        result.isIncomplete = false;  // 表示这是完整的补全列表
        result.items = std::move(allItems);

        spdlog::info("{}: Provided {} completion items", GetProviderName(), result.items.size());

        return result;
    }

    std::string CompletionProvider::ExtractPrefix(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position)
    {
        // TODO: 实现从文档内容和位置计算前缀
        // 这需要访问文档管理器来获取文档内容
        // 现在返回空字符串
        spdlog::trace("{}: ExtractPrefix not implemented, returning empty string", GetProviderName());
        return "";
    }

    std::vector<protocol::CompletionItem> CompletionProvider::ProvideKeywordCompletions(const std::string& prefix)
    {
        std::vector<protocol::CompletionItem> items;

        // 从 tsl_keywords_ 获取补全项
        auto tslItems = tsl_keywords_.GetCompletionItems(prefix);

        for (const auto& tslItem : tslItems) {
            protocol::CompletionItem item;
            item.label = tslItem.label;
            item.kind = protocol::CompletionItemKind::kKeyword;
            item.detail = "TSL Keyword";

            // 创建文档内容
            protocol::MarkupContent documentation;
            documentation.kind = protocol::MarkupKindLiterals::PlainText;
            documentation.value = "TSL language keyword";
            item.documentation = documentation;

            item.insertText = tslItem.label;

            items.push_back(item);
        }

        spdlog::debug("{}: Found {} keyword completions", GetProviderName(), items.size());
        return items;
    }

    std::vector<protocol::CompletionItem> CompletionProvider::ProvideContextualCompletions(const protocol::TextDocumentIdentifier& textDocument, const protocol::Position& position, const std::string& prefix)
    {
        spdlog::debug("{}: Processing contextual completions for URI: {}", GetProviderName(), textDocument.uri);

        std::vector<protocol::CompletionItem> items;

        // TODO: 基于上下文提供补全
        // 示例：添加一个变量补全
        if (!prefix.empty() && prefix[0] == '$')
        {
            protocol::CompletionItem varItem;
            varItem.label = "$myVariable";
            varItem.kind = protocol::CompletionItemKind::kVariable;
            varItem.detail = "Local variable";
            varItem.insertText = "$myVariable";

            protocol::MarkupContent doc;
            doc.kind = protocol::MarkupKindLiterals::Markdown;
            doc.value = "Example variable completion";
            varItem.documentation = doc;

            items.push_back(varItem);
        }

        spdlog::debug("{}: Found {} contextual completions", GetProviderName(), items.size());
        return items;
    }
}
