// rename.cpp
#include <spdlog/spdlog.h>
#include <regex>
#include <cstring>
#include <algorithm>
#include "./rename.hpp"
#include "../../protocol/transform/facade.hpp"
#include "../../service/document.hpp"
#include "../../service/symbol.hpp"

namespace lsp::provider::text_document
{
    std::string Rename::GetMethod() const
    {
        return "textDocument/rename";
    }

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

    std::string Rename::ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context)
    {
        spdlog::debug("TextDocumentRenameProvider: 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::RenameParams params =
            transform::As<protocol::RenameParams>(request.params.value());

        // 验证新名称是否有效
        if (!IsValidIdentifier(params.newName))
        {
            spdlog::warn("{}: Invalid new name: '{}'", GetProviderName(), params.newName);
            return BuildErrorResponseMessage(request, protocol::ErrorCodes::InvalidParams, "'" + params.newName + "' is not a valid identifier");
        }

        auto workspace_edit_opt = BuildRenameResponse(params, context);

        protocol::ResponseMessage response;
        response.id = request.id;

        if (workspace_edit_opt.has_value())
        {
            response.result = transform::LSPAny(*workspace_edit_opt);
        }
        else
        {
            // 返回 null 表示没有需要修改的内容或无法重命名
            response.result = std::nullopt;
        }

        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::optional<protocol::WorkspaceEdit> Rename::BuildRenameResponse(const protocol::RenameParams& params, ExecutionContext& context)
    {
        spdlog::trace("{}: Processing rename request for URI='{}', Position=({}, {}), NewName='{}'",
                      GetProviderName(),
                      params.textDocument.uri,
                      params.position.line,
                      params.position.character,
                      params.newName);

        // 获取要重命名的标识符
        std::string old_name = GetIdentifierAtPosition(params.textDocument.uri, params.position, context);

        if (old_name.empty())
        {
            spdlog::info("{}: No identifier at position", GetProviderName());
            return std::nullopt;
        }

        // 验证是否可以重命名
        if (!CanRename(old_name))
        {
            spdlog::warn("{}: Cannot rename '{}' (reserved keyword or built-in)",
                         GetProviderName(),
                         old_name);
            return std::nullopt;
        }

        // 如果新旧名称相同，直接返回
        if (old_name == params.newName)
        {
            spdlog::info("{}: New name is same as old name", GetProviderName());
            return std::nullopt;
        }

        spdlog::debug("{}: Renaming '{}' to '{}'", GetProviderName(), old_name, params.newName);

        // 查找所有需要重命名的位置
        auto locations = FindRenameLocations(params.textDocument.uri, old_name, context);

        if (locations.empty())
        {
            spdlog::info("{}: No references found for '{}'", GetProviderName(), old_name);
            return std::nullopt;
        }

        // 构建 WorkspaceEdit
        protocol::WorkspaceEdit workspace_edit;

        // 按文档组织编辑
        for (const auto& location : locations)
        {
            protocol::TextEdit edit;
            edit.range = location.range;
            edit.newText = params.newName;

            workspace_edit.changes[location.uri].push_back(edit);
        }

        // 对每个文档的编辑按位置排序（从后往前，避免位置偏移）
        for (auto& [uri, edits] : workspace_edit.changes)
        {
            std::sort(edits.begin(), edits.end(), [](const protocol::TextEdit& a, const protocol::TextEdit& b) {
                if (a.range.start.line != b.range.start.line)
                    return a.range.start.line > b.range.start.line;
                return a.range.start.character > b.range.start.character;
            });
        }

        spdlog::info("{}: Found {} locations to rename in {} document(s)",
                     GetProviderName(),
                     locations.size(),
                     workspace_edit.changes.size());

        return workspace_edit;
    }

    std::vector<protocol::Location> Rename::FindRenameLocations(const protocol::DocumentUri& uri, const std::string& old_name, ExecutionContext& context)
    {
        std::vector<protocol::Location> locations;

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

        // TODO: 扩展到多文档
        // 当前只在单个文档中查找
        auto content = document_service.GetContent(uri);
        auto tree = document_service.GetSyntaxTree(uri);

        if (!content.has_value() || !tree)
        {
            spdlog::warn("{}: Document not found or no syntax tree: {}",
                         GetProviderName(),
                         uri);
            return locations;
        }

        // 查找所有标识符位置
        std::vector<protocol::Range> ranges;
        TSNode root = ts_tree_root_node(tree);
        FindIdentifiersInNode(root, old_name, *content, ranges);

        // 转换为Location
        for (const auto& range : ranges)
        {
            protocol::Location location;
            location.uri = uri;
            location.range = range;
            locations.push_back(location);
        }

        spdlog::debug("{}: Found {} occurrences of '{}' in document",
                      GetProviderName(),
                      locations.size(),
                      old_name);

        return locations;
    }

    void Rename::FindIdentifiersInNode(TSNode node, const std::string& identifier, const std::string& content, std::vector<protocol::Range>& ranges)
    {
        const char* node_type = ts_node_type(node);

        // 处理标识符节点
        if (strcmp(node_type, kIdentifier) == 0)
        {
            uint32_t start = ts_node_start_byte(node);
            uint32_t end = ts_node_end_byte(node);

            if (start < content.length() && end <= content.length())
            {
                std::string text = content.substr(start, end - start);

                if (text == identifier)
                {
                    TSPoint start_point = ts_node_start_point(node);
                    TSPoint end_point = ts_node_end_point(node);

                    protocol::Range range;
                    range.start.line = start_point.row;
                    range.start.character = start_point.column;
                    range.end.line = end_point.row;
                    range.end.character = end_point.column;

                    ranges.push_back(range);

                    spdlog::trace("{}: Found identifier '{}' at {}:{}",
                                  GetProviderName(),
                                  identifier,
                                  start_point.row,
                                  start_point.column);
                }
            }
        }

        // 递归处理子节点
        uint32_t child_count = ts_node_child_count(node);
        for (uint32_t i = 0; i < child_count; i++)
        {
            TSNode child = ts_node_child(node, i);
            FindIdentifiersInNode(child, identifier, content, ranges);
        }
    }

    std::string Rename::GetIdentifierAtPosition(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context)
    {
        auto& document_service = context.GetService<service::Document>();

        auto content = document_service.GetContent(uri);
        auto tree = document_service.GetSyntaxTree(uri);

        if (!content.has_value() || !tree)
        {
            spdlog::warn("{}: Cannot get content or tree for {}", GetProviderName(), uri);
            return "";
        }

        // 计算字节位置
        size_t byte_offset = 0;
        size_t current_line = 0;
        size_t current_col = 0;

        for (size_t i = 0; i < content->length(); i++)
        {
            if (current_line == position.line)
            {
                if (current_col == position.character)
                {
                    byte_offset = i;
                    break;
                }
                current_col++;
            }

            if ((*content)[i] == '\n')
            {
                current_line++;
                current_col = 0;
            }
        }

        // 获取该位置的节点
        TSNode root = ts_tree_root_node(tree);
        TSNode node = ts_node_descendant_for_byte_range(root, byte_offset, byte_offset);

        // 向上查找标识符节点
        while (!ts_node_is_null(node))
        {
            const char* node_type = ts_node_type(node);
            if (strcmp(node_type, kIdentifier) == 0)
            {
                uint32_t start = ts_node_start_byte(node);
                uint32_t end = ts_node_end_byte(node);

                if (start < content->length() && end <= content->length())
                {
                    std::string identifier = content->substr(start, end - start);
                    spdlog::debug("{}: Found identifier '{}' at position",
                                  GetProviderName(),
                                  identifier);
                    return identifier;
                }
            }
            node = ts_node_parent(node);
        }

        spdlog::debug("{}: No identifier found at position {}:{}",
                      GetProviderName(),
                      position.line,
                      position.character);
        return "";
    }

    bool Rename::CanRename(const std::string& identifier)
    {
        // 空标识符不能重命名
        if (identifier.empty())
        {
            return false;
        }

        // 转换为小写以进行不区分大小写的比较
        std::string lower_id = identifier;
        std::transform(lower_id.begin(), lower_id.end(), lower_id.begin(), ::tolower);

        // 不能重命名关键字
        if (kReservedKeywords.find(lower_id) != kReservedKeywords.end())
        {
            spdlog::debug("Rename: '{}' is a reserved keyword", identifier);
            return false;
        }

        // 可以添加其他限制
        // 例如：不允许重命名系统函数、内置类型等

        return true;
    }

    bool Rename::IsValidIdentifier(const std::string& new_name)
    {
        // 检查是否为空
        if (new_name.empty())
        {
            return false;
        }

        // 检查是否是保留关键字
        std::string lower_name = new_name;
        std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);

        if (kReservedKeywords.find(lower_name) != kReservedKeywords.end())
        {
            spdlog::debug("Rename: '{}' is a reserved keyword", new_name);
            return false;
        }

        // TSF标识符规则：以字母或下划线开头，后跟字母、数字或下划线
        // 第一个字符必须是字母或下划线
        if (!std::isalpha(new_name[0]) && new_name[0] != '_')
        {
            return false;
        }

        // 后续字符可以是字母、数字或下划线
        for (size_t i = 1; i < new_name.length(); i++)
        {
            char c = new_name[i];
            if (!std::isalnum(c) && c != '_')
            {
                return false;
            }
        }

        return true;
    }

    bool Rename::IsDefinitionNode(TSNode node, const std::string& identifier, const std::string& content)
    {
        TSNode parent = ts_node_parent(node);
        if (ts_node_is_null(parent))
            return false;

        const char* parent_type = ts_node_type(parent);

        // 检查是否是函数/类/变量定义
        if (strcmp(parent_type, kFunctionDefinition) == 0 ||
            strcmp(parent_type, kFunctionDeclaration) == 0 ||
            strcmp(parent_type, kClassDefinition) == 0 ||
            strcmp(parent_type, kVarStatement) == 0 ||
            strcmp(parent_type, kStaticStatement) == 0 ||
            strcmp(parent_type, kGlobalStatement) == 0 ||
            strcmp(parent_type, kConstStatement) == 0 ||
            strcmp(parent_type, kMethodDeclaration) == 0 ||
            strcmp(parent_type, kMethodDeclarationOnly) == 0 ||
            strcmp(parent_type, kMethodWithModifier) == 0 ||
            strcmp(parent_type, kMethodWithImplementation) == 0 ||
            strcmp(parent_type, kPropertyDeclaration) == 0)
        {
            // 检查是否是名称字段
            TSNode name_node = ts_node_child_by_field_name(parent, "name", 4);
            if (!ts_node_is_null(name_node))
            {
                return ts_node_eq(name_node, node);
            }
        }

        // 检查是否是赋值表达式的左侧（变量定义）
        if (strcmp(parent_type, kAssignmentExpression) == 0)
        {
            TSNode left_node = ts_node_child_by_field_name(parent, "left", 4);
            if (!ts_node_is_null(left_node))
            {
                // 检查节点是否在左侧
                TSNode current = node;
                while (!ts_node_is_null(current))
                {
                    if (ts_node_eq(current, left_node))
                        return true;
                    current = ts_node_parent(current);
                    if (ts_node_eq(current, parent))
                        break;
                }
            }
        }

        // 检查是否是变量声明
        if (strcmp(parent_type, kVarDeclaration) == 0 ||
            strcmp(parent_type, kStaticDeclaration) == 0 ||
            strcmp(parent_type, kGlobalDeclaration) == 0)
        {
            return true;
        }

        return false;
    }
}
