#include <spdlog/spdlog.h>
#include "../../language/keyword/repo.hpp"
#include "../../service/symbol.hpp"
#include "../../protocol/transform/facade.hpp"
#include "../text_document/completion.hpp" // 临时用CompletionInfo
#include "./resolve.hpp"

namespace lsp::provider::completion_item
{
    std::string Resolve::GetMethod() const
    {
        return "completionItem/resolve";
    }

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

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

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

        protocol::CompletionItem item = transform::As<protocol::CompletionItem>(request.params.value());
        protocol::CompletionItem resolved_item = ResolveCompletionItem(item, execution_context);

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

        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();
    }

    protocol::CompletionItem Resolve::ResolveCompletionItem(const protocol::CompletionItem& item, ExecutionContext& execution_context)
    {
        spdlog::trace("{}: Resolving item '{}' of kind {}", GetProviderName(), item.label, static_cast<int>(item.kind.value()));

        protocol::CompletionItem resolved = item;

        // 检查 data 字段中的上下文信息（优先级最高）
        if (item.data.has_value())
        {
            try
            {
                text_document::CompletionInfo ci = transform::As<text_document::CompletionInfo>(item.data.value());
                spdlog::trace("{}: Item '{}' has data context: '{}'", GetProviderName(), item.label, ci.class_name);

                // 类方法上下文: "class_method_context:ClassName"
                if (ci.type.find("class_method_context") == 0)
                {
                    spdlog::debug("{}: Resolving as class method", GetProviderName());
                    ResolveClassMethod(resolved, execution_context);
                    return resolved;
                }
            }
            catch (const std::exception& e)
            {
                spdlog::warn("{}: Failed to parse data field for item '{}': {}", GetProviderName(), item.label, e.what());
                // 继续正常处理
            }
        }

        // 根据补全项类型进行解析
        if (!item.kind.has_value())
        {
            spdlog::warn("{}: Item '{}' has no kind specified", GetProviderName(), item.label);
            return resolved;
        }

        switch (item.kind.value())
        {
        case protocol::CompletionItemKind::Keyword:
            ResolveKeyword(resolved);
            break;

        case protocol::CompletionItemKind::Function:
        case protocol::CompletionItemKind::Method:
            ResolveFunction(resolved, execution_context);
            break;

        case protocol::CompletionItemKind::Class:
        case protocol::CompletionItemKind::Constructor:
            ResolveClass(resolved, execution_context);
            break;

        case protocol::CompletionItemKind::Module:
            ResolveUnit(resolved, execution_context);
            break;

        case protocol::CompletionItemKind::Variable:
        case protocol::CompletionItemKind::Property:
            ResolveVariable(resolved, execution_context);
            break;

        default:
            spdlog::trace("{}: Unknown item kind {} for '{}', skipping resolution",
                          GetProviderName(),
                          static_cast<int>(item.kind.value()),
                          item.label);
            break;
        }

        return resolved;
    }

    void Resolve::ResolveKeyword(protocol::CompletionItem& item)
    {
        auto keyword_info = language::keyword::Repo::Instance().FindByName(item.label);
        if (!keyword_info)
        {
            spdlog::warn("{}: Keyword '{}' not found", GetProviderName(), item.label);
            return;
        }

        item.documentation = documentation::BuildKeywordDocumentation(keyword_info->description);
        spdlog::trace("{}: Resolved keyword '{}'", GetProviderName(), item.label);
    }

    void Resolve::ResolveFunction(protocol::CompletionItem& item, ExecutionContext& execution_context)
    {
        spdlog::trace("{}: Resolving function '{}'", GetProviderName(), item.label);

        // 查找函数符号
        auto result = FindFunctionSymbol(item.label, execution_context);

        if (!result.symbol)
        {
            spdlog::warn("{}: Function '{}' not found in symbol repositories", GetProviderName(), item.label);
            return;
        }

        // 添加文档
        item.documentation = documentation::BuildFunctionDocumentation(*result.symbol, result.source_file, result.source_type);

        // 添加代码片段
        item.insertText = snippet::BuildFunctionCallSnippet(*result.symbol);
        item.insertTextFormat = protocol::InsertTextFormat::Snippet;

        spdlog::trace("{}: Resolved function '{}' from {} ({})", GetProviderName(), item.label, result.source_type, result.source_file);
    }

    void Resolve::ResolveClass(protocol::CompletionItem& item, ExecutionContext& execution_context)
    {
        spdlog::trace("{}: Resolving class '{}'", GetProviderName(), item.label);

        // 查找类符号
        auto result = FindClassSymbol(item.label, execution_context);

        if (!result.symbol)
        {
            spdlog::trace("{}: Class '{}' not found in symbol repositories", GetProviderName(), item.label);
            return;
        }

        // 添加文档
        item.documentation = documentation::BuildClassDocumentation(item.label, result.source_file, result.source_type);

        spdlog::trace("{}: Resolved class '{}' from {} ({})",
                      GetProviderName(),
                      item.label,
                      result.source_type,
                      result.source_file);
    }

    void Resolve::ResolveClassMethod(protocol::CompletionItem& item, ExecutionContext& execution_context)
    {
        spdlog::debug("{}: Resolving class method '{}'", GetProviderName(), item.label);

        text_document::CompletionInfo ci = transform::As<text_document::CompletionInfo>(item.data.value());
        // 查找类方法符号
        std::string class_name = ci.class_name;
        auto result = FindClassMethodSymbol(class_name, item.label, execution_context);

        if (!result.symbol)
        {
            spdlog::warn("{}: Class method '{}' not found in class '{}'",
                         GetProviderName(),
                         item.label,
                         class_name);
            return;
        }

        // 添加文档
        item.documentation = documentation::BuildClassMethodDocumentation(
            class_name, *result.symbol, result.source_file, result.source_type);

        // 添加代码片段
        item.insertText = snippet::BuildFunctionCallSnippet(*result.symbol);
        item.insertTextFormat = protocol::InsertTextFormat::Snippet;

        spdlog::debug("{}: Resolved class method '{}.{}' from {} ({})",
                      GetProviderName(),
                      class_name,
                      item.label,
                      result.source_type,
                      result.source_file);
    }

    void Resolve::ResolveUnit(protocol::CompletionItem& item, ExecutionContext& execution_context)
    {
        spdlog::trace("{}: Resolving unit '{}'", GetProviderName(), item.label);

        auto symbol_service = execution_context.GetService<service::Symbol>();

        // 先在工作区查找
        auto workspace_unit = symbol_service->WorkspaceRepo().FindUnit(item.label);
        if (workspace_unit.has_value())
        {
            item.documentation = documentation::BuildUnitDocumentation(
                item.label, workspace_unit->file_path, "Workspace");
            spdlog::trace("{}: Resolved unit '{}' from Workspace", GetProviderName(), item.label);
            return;
        }

        // 在系统库查找
        auto system_unit = symbol_service->SystemRepo().FindUnit(item.label);
        if (system_unit.has_value())
        {
            item.documentation = documentation::BuildUnitDocumentation(
                item.label, system_unit->file_path, "System");
            spdlog::trace("{}: Resolved unit '{}' from System", GetProviderName(), item.label);
            return;
        }

        spdlog::warn("{}: Unit '{}' not found in any repository", GetProviderName(), item.label);
    }

    void Resolve::ResolveVariable(protocol::CompletionItem& item, ExecutionContext& execution_context)
    {
        // 变量解析：简化实现，暂时只提供基本信息
        spdlog::trace("{}: Variable/Property resolution for '{}' - basic info only",
                      GetProviderName(),
                      item.label);

        // TODO: 可以在这里添加变量类型推断等高级功能
    }

    // ==================== 辅助函数：查找符号 ====================

    Resolve::SymbolLookupResult Resolve::FindFunctionSymbol(
        const std::string& name,
        ExecutionContext& execution_context)
    {
        SymbolLookupResult result;
        auto symbol_service = execution_context.GetService<service::Symbol>();

        spdlog::trace("FindFunctionSymbol: Searching for '{}'", name);

        // 1. 在工作区查找
        auto workspace_file = symbol_service->WorkspaceRepo().FindFunction(name);
        if (workspace_file.has_value())
        {
            spdlog::trace("FindFunctionSymbol: Found '{}' in workspace", name);

            // 在 exported_symbols 中查找匹配的函数
            for (const auto& symbol : workspace_file->exported_symbols)
            {
                if (symbol.name == name &&
                    (symbol.kind == protocol::SymbolKind::Function ||
                     symbol.kind == protocol::SymbolKind::Method))
                {
                    result.symbol = symbol;
                    result.source_file = workspace_file->file_path;
                    result.source_type = "Workspace";
                    return result;
                }
            }
        }

        // 2. 在系统库查找
        auto system_file = symbol_service->SystemRepo().FindFunction(name);
        if (system_file.has_value())
        {
            spdlog::trace("FindFunctionSymbol: Found '{}' in system", name);

            for (const auto& symbol : system_file->exported_symbols)
            {
                if (symbol.name == name &&
                    (symbol.kind == protocol::SymbolKind::Function ||
                     symbol.kind == protocol::SymbolKind::Method))
                {
                    result.symbol = symbol;
                    result.source_file = system_file->file_path;
                    result.source_type = "System";
                    return result;
                }
            }
        }

        spdlog::trace("FindFunctionSymbol: Function '{}' not found", name);
        return result;
    }

    Resolve::SymbolLookupResult Resolve::FindClassSymbol(
        const std::string& name,
        ExecutionContext& execution_context)
    {
        SymbolLookupResult result;
        auto symbol_service = execution_context.GetService<service::Symbol>();

        spdlog::trace("FindClassSymbol: Searching for '{}'", name);

        // 1. 在工作区查找
        auto workspace_file = symbol_service->WorkspaceRepo().FindClass(name);
        if (workspace_file.has_value())
        {
            spdlog::trace("FindClassSymbol: Found '{}' in workspace", name);

            // 对于类，我们可以返回一个代表类的 MemberSymbol
            // 或者只返回文件信息用于文档生成
            service::symbol::MemberSymbol class_symbol;
            class_symbol.name = name;
            class_symbol.kind = protocol::SymbolKind::Class;

            result.symbol = class_symbol;
            result.source_file = workspace_file->file_path;
            result.source_type = "Workspace";
            return result;
        }

        // 2. 在系统库查找
        auto system_file = symbol_service->SystemRepo().FindClass(name);
        if (system_file.has_value())
        {
            spdlog::trace("FindClassSymbol: Found '{}' in system", name);

            service::symbol::MemberSymbol class_symbol;
            class_symbol.name = name;
            class_symbol.kind = protocol::SymbolKind::Class;

            result.symbol = class_symbol;
            result.source_file = system_file->file_path;
            result.source_type = "System";
            return result;
        }

        spdlog::trace("FindClassSymbol: Class '{}' not found", name);
        return result;
    }

    Resolve::SymbolLookupResult Resolve::FindClassMethodSymbol(
        const std::string& class_name,
        const std::string& method_name,
        ExecutionContext& execution_context)
    {
        SymbolLookupResult result;
        auto symbol_service = execution_context.GetService<service::Symbol>();

        spdlog::debug("FindClassMethodSymbol: Searching for '{}.{}'", class_name, method_name);

        // 1. 在工作区查找
        auto workspace_file = symbol_service->WorkspaceRepo().FindClass(class_name);
        if (workspace_file.has_value())
        {
            spdlog::trace("FindClassMethodSymbol: Found class '{}' in workspace with {} exported symbols",
                          class_name,
                          workspace_file->exported_symbols.size());

            // 在 exported_symbols 中查找匹配的类方法
            for (const auto& symbol : workspace_file->exported_symbols)
            {
                spdlog::trace("FindClassMethodSymbol: Checking symbol '{}', is_class_method={}",
                              symbol.name,
                              symbol.is_class_method);

                if (symbol.name == method_name && symbol.is_class_method)
                {
                    result.symbol = symbol;
                    result.source_file = workspace_file->file_path;
                    result.source_type = "Workspace";
                    spdlog::debug("FindClassMethodSymbol: Found '{}.{}' in workspace", class_name, method_name);
                    return result;
                }
            }

            spdlog::warn("FindClassMethodSymbol: Class '{}' found but method '{}' not found in exported symbols",
                         class_name,
                         method_name);
        }
        else
        {
            spdlog::warn("FindClassMethodSymbol: Class '{}' not found in workspace", class_name);
        }

        // 2. 在系统库查找
        auto system_file = symbol_service->SystemRepo().FindClass(class_name);
        if (system_file.has_value())
        {
            spdlog::trace("FindClassMethodSymbol: Found class '{}' in system with {} exported symbols",
                          class_name,
                          system_file->exported_symbols.size());

            for (const auto& symbol : system_file->exported_symbols)
            {
                if (symbol.name == method_name && symbol.is_class_method)
                {
                    result.symbol = symbol;
                    result.source_file = system_file->file_path;
                    result.source_type = "System";
                    spdlog::debug("FindClassMethodSymbol: Found '{}.{}' in system", class_name, method_name);
                    return result;
                }
            }

            spdlog::warn("FindClassMethodSymbol: Class '{}' found in system but method '{}' not found",
                         class_name,
                         method_name);
        }
        else
        {
            spdlog::warn("FindClassMethodSymbol: Class '{}' not found in system", class_name);
        }

        spdlog::warn("FindClassMethodSymbol: Method '{}.{}' not found in any repository",
                     class_name,
                     method_name);
        return result;
    }

    // ==================== Documentation ====================

    namespace documentation
    {
        protocol::MarkupContent BuildKeywordDocumentation(const std::string& description)
        {
            protocol::MarkupContent content;
            content.kind = protocol::MarkupKindLiterals::Markdown;

            std::stringstream doc;
            doc << "### Keyword\n\n";
            doc << description << "\n";

            content.value = doc.str();
            return content;
        }

        protocol::MarkupContent BuildFunctionDocumentation(
            const service::symbol::MemberSymbol& symbol,
            const std::string& file_path,
            const std::string& source_type)
        {
            protocol::MarkupContent content;
            content.kind = protocol::MarkupKindLiterals::Markdown;

            std::stringstream doc;

            // 来源信息
            doc << "### Function";
            if (!source_type.empty())
            {
                doc << " (" << source_type << ")";
            }
            doc << "\n\n";

            // 函数签名
            doc << "```pascal\n";
            doc << "function " << symbol.name << "(";

            for (size_t i = 0; i < symbol.parameters.size(); ++i)
            {
                if (i > 0)
                    doc << ", ";
                doc << symbol.parameters[i].name;
                if (!symbol.parameters[i].type.empty())
                    doc << ": " << symbol.parameters[i].type;
            }
            doc << ")";

            if (symbol.return_type.has_value() && !symbol.return_type->empty())
            {
                doc << ": " << *symbol.return_type;
            }
            doc << "\n```\n\n";

            // 参数列表
            if (!symbol.parameters.empty())
            {
                doc << "#### Parameters\n\n";
                for (const auto& param : symbol.parameters)
                {
                    doc << "- **" << param.name << "**";

                    if (!param.type.empty())
                        doc << ": `" << param.type << "`";

                    if (param.has_default)
                        doc << " *(optional)*";

                    doc << "\n";
                }
                doc << "\n";
            }

            // 返回值类型
            if (symbol.return_type.has_value() && !symbol.return_type->empty())
            {
                doc << "#### Returns\n\n";
                doc << "`" << *symbol.return_type << "`\n\n";
            }

            // 文件路径
            if (!file_path.empty())
            {
                doc << "---\n\n";
                doc << "*Source: `" << file_path << "`*\n";
            }

            content.value = doc.str();
            return content;
        }

        protocol::MarkupContent BuildClassDocumentation(
            const std::string& class_name,
            const std::string& file_path,
            const std::string& source_type)
        {
            protocol::MarkupContent content;
            content.kind = protocol::MarkupKindLiterals::Markdown;

            std::stringstream doc;

            // 来源信息
            doc << "### Class";
            if (!source_type.empty())
            {
                doc << " (" << source_type << ")";
            }
            doc << "\n\n";

            // 类名
            doc << "```pascal\n";
            doc << "class " << class_name;
            doc << "\n```\n\n";

            // 文件路径
            if (!file_path.empty())
            {
                doc << "---\n\n";
                doc << "*Source: `" << file_path << "`*\n";
            }

            content.value = doc.str();
            return content;
        }

        protocol::MarkupContent BuildClassMethodDocumentation(
            const std::string& class_name,
            const service::symbol::MemberSymbol& symbol,
            const std::string& file_path,
            const std::string& source_type)
        {
            protocol::MarkupContent content;
            content.kind = protocol::MarkupKindLiterals::Markdown;

            std::stringstream doc;

            // 来源信息
            doc << "### Class Method";
            if (!source_type.empty())
            {
                doc << " (" << source_type << ")";
            }
            doc << "\n\n";

            // 方法签名
            doc << "```pascal\n";
            doc << "class method " << class_name << "." << symbol.name << "(";

            for (size_t i = 0; i < symbol.parameters.size(); ++i)
            {
                if (i > 0)
                    doc << ", ";
                doc << symbol.parameters[i].name;
                if (!symbol.parameters[i].type.empty())
                    doc << ": " << symbol.parameters[i].type;
            }
            doc << ")";

            if (symbol.return_type.has_value() && !symbol.return_type->empty())
            {
                doc << ": " << *symbol.return_type;
            }
            doc << "\n```\n\n";

            // 参数列表
            if (!symbol.parameters.empty())
            {
                doc << "#### Parameters\n\n";
                for (const auto& param : symbol.parameters)
                {
                    doc << "- **" << param.name << "**";

                    if (!param.type.empty())
                        doc << ": `" << param.type << "`";

                    if (param.has_default)
                        doc << " *(optional)*";

                    doc << "\n";
                }
                doc << "\n";
            }

            // 返回值类型
            if (symbol.return_type.has_value() && !symbol.return_type->empty())
            {
                doc << "#### Returns\n\n";
                doc << "`" << *symbol.return_type << "`\n\n";
            }

            // 文件路径
            if (!file_path.empty())
            {
                doc << "---\n\n";
                doc << "*Source: `" << file_path << "`*\n";
            }

            content.value = doc.str();
            return content;
        }

        protocol::MarkupContent BuildUnitDocumentation(
            const std::string& unit_name,
            const std::string& file_path,
            const std::string& source_type)
        {
            protocol::MarkupContent content;
            content.kind = protocol::MarkupKindLiterals::Markdown;

            std::stringstream doc;

            // 来源信息
            doc << "### Unit";
            if (!source_type.empty())
            {
                doc << " (" << source_type << ")";
            }
            doc << "\n\n";

            // 单元名
            doc << "```pascal\n";
            doc << "unit " << unit_name;
            doc << "\n```\n\n";

            // 文件路径
            if (!file_path.empty())
            {
                doc << "---\n\n";
                doc << "*Source: `" << file_path << "`*\n";
            }

            content.value = doc.str();
            return content;
        }

        std::string FormatFunctionMarkdown(const service::symbol::MemberSymbol& symbol)
        {
            std::stringstream doc;

            doc << "#### function\n\n";
            doc << "`" << symbol.name << "`";
            doc << "\n\n";

            // 参数列表
            if (!symbol.parameters.empty())
            {
                doc << "##### parameters\n\n";
                for (const auto& param : symbol.parameters)
                {
                    doc << "- `" << param.name << "`";

                    if (!param.type.empty())
                        doc << ": `" << param.type << "`";
                    doc << "\n";
                }
                doc << "\n";
            }

            // 返回值类型
            if (symbol.return_type.has_value() && !symbol.return_type->empty())
            {
                doc << "##### returns\n\n";
                doc << "`" << *symbol.return_type << "`\n\n";
            }

            return doc.str();
        }
    }

    // ==================== Snippet ====================

    namespace snippet
    {
        std::string BuildFunctionCallSnippet(const service::symbol::MemberSymbol& symbol)
        {
            std::stringstream snippet_builder;
            snippet_builder << symbol.name << "(";

            if (!symbol.parameters.empty())
            {
                for (size_t i = 0; i < symbol.parameters.size(); ++i)
                {
                    if (i > 0)
                    {
                        snippet_builder << ", ";
                    }

                    // 生成占位符 ${n:placeholder}
                    snippet_builder << "${" << (i + 1) << ":";

                    // 包含参数名和可选的类型提示
                    const auto& param = symbol.parameters[i];
                    if (!param.type.empty())
                    {
                        snippet_builder << param.name << ": " << param.type;
                    }
                    else
                    {
                        snippet_builder << param.name;
                    }

                    snippet_builder << "}";
                }
            }

            snippet_builder << ")$0";
            return snippet_builder.str();
        }

        std::string BuildConstructorSnippet(
            const std::string& class_name,
            const service::symbol::MemberSymbol* constructor)
        {
            std::stringstream ss;
            ss << class_name;

            if (!constructor || constructor->parameters.empty())
            {
                // 无参构造函数
                ss << "()$0";
            }
            else
            {
                // 有参构造函数：生成参数占位符
                ss << "(";

                for (size_t i = 0; i < constructor->parameters.size(); ++i)
                {
                    if (i > 0)
                        ss << ", ";

                    // LSP snippet 格式：${序号:占位文本}
                    ss << "${" << (i + 1) << ":";

                    // 参数名作为占位文本
                    ss << constructor->parameters[i].name;

                    // 如果有类型，添加类型提示
                    if (!constructor->parameters[i].type.empty())
                    {
                        ss << ": " << constructor->parameters[i].type;
                    }

                    ss << "}";
                }

                ss << ")$0";
            }

            return ss.str();
        }
    }
}
