#include <algorithm>
#include "./document.hpp"

namespace lsp::services
{
    // ===== Document 实现 =====

    Document::Document(const protocol::TextDocumentItem& item) :
        item_(item), last_modified_time_(std::chrono::system_clock::now())
    {
        UpdateInternalState();
        spdlog::trace("Created document: {} (version {}, {} bytes)", item_.uri, item_.version, item_.text.length());
    }

    void Document::SetContent(int32_t newVersion, const std::string& newText)
    {
        item_.version = newVersion;
        item_.text = newText;
        is_dirty_ = true;
        last_modified_time_ = std::chrono::system_clock::now();
        UpdateInternalState();

        spdlog::trace("Document {} updated to version {} ({} bytes)", item_.uri, item_.version, item_.text.length());
    }

    void Document::ApplyContentChange(protocol::integer version, const std::vector<protocol::TextDocumentContentChangeEvent>& changes)
    {
        // 应用所有变更
        for (const auto& change : changes)
        {
            ApplyContentChange(change);
        }

        item_.version = version;
        is_dirty_ = true;
        last_modified_time_ = std::chrono::system_clock::now();
        UpdateInternalState();

        spdlog::trace("Document {} updated to version {} with {} changes", item_.uri, item_.version, changes.size());
    }

    void Document::ApplyContentChange(const protocol::TextDocumentContentChangeEvent& change)
    {
        // 增量更新
        size_t startOffset = PositionToOffset(change.range.start);
        size_t endOffset = PositionToOffset(change.range.end);

        // 替换指定范围
        item_.text = item_.text.substr(0, startOffset) + change.text + item_.text.substr(endOffset);
    }

    size_t Document::PositionToOffset(const protocol::Position& position) const
    {
        if (position.line >= lines_.size())
        {
            return item_.text.length();
        }

        size_t offset = line_offsets_[position.line];

        // 根据编码计算字符偏移
        if (encoding_ == protocol::PositionEncodingKindLiterals::UTF8)
        {
            // 直接使用字节偏移
            offset += std::min(static_cast<size_t>(position.character), lines_[position.line].length());
        }
        else
        {
            // UTF-16 或 UTF-32
            offset += CharacterToByteOffset(lines_[position.line], position.character);
        }

        return offset;
    }

    protocol::Position Document::OffsetToPosition(size_t offset) const
    {
        protocol::Position pos;
        pos.line = 0;
        pos.character = 0;

        // 二分查找行号
        auto it = std::upper_bound(line_offsets_.begin(), line_offsets_.end(), offset);
        if (it != line_offsets_.begin())
        {
            --it;
            pos.line = static_cast<int32_t>(std::distance(line_offsets_.begin(), it));
            size_t lineOffset = *it;
            size_t byteOffset = offset - lineOffset;

            // 根据编码计算字符位置
            if (encoding_ == protocol::PositionEncodingKindLiterals::UTF8)
            {
                pos.character = static_cast<int32_t>(byteOffset);
            }
            else
            {
                pos.character = ByteOffsetToCharacter(lines_[pos.line], byteOffset);
            }
        }

        return pos;
    }

    std::string Document::GetTextInRange(const protocol::Range& range) const
    {
        size_t start = PositionToOffset(range.start);
        size_t end = PositionToOffset(range.end);

        if (start >= item_.text.length())
        {
            return "";
        }

        end = std::min(end, item_.text.length());
        return item_.text.substr(start, end - start);
    }

    std::optional<char> Document::GetCharAt(const protocol::Position& position) const
    {
        if (position.line >= lines_.size())
        {
            return std::nullopt;
        }

        const std::string& line = lines_[position.line];
        size_t byteOffset = CharacterToByteOffset(line, position.character);

        if (byteOffset >= line.length())
        {
            return std::nullopt;
        }

        return line[byteOffset];
    }

    std::string Document::GetLine(size_t lineNumber) const
    {
        if (lineNumber < lines_.size())
        {
            return lines_[lineNumber];
        }
        return "";
    }

    std::string Document::GetLineAt(const protocol::Position& position) const
    {
        return GetLine(position.line);
    }

    std::string Document::GetWordAt(const protocol::Position& position) const
    {
        if (position.line >= lines_.size())
        {
            return "";
        }

        const std::string& line = lines_[position.line];
        size_t bytePos = CharacterToByteOffset(line, position.character);

        // 找到单词边界
        size_t start = bytePos;
        while (start > 0 && IsWordChar(line[start - 1]))
        {
            --start;
        }

        size_t end = bytePos;
        while (end < line.length() && IsWordChar(line[end]))
        {
            ++end;
        }

        return line.substr(start, end - start);
    }

    protocol::Range Document::GetWordRangeAt(const protocol::Position& position) const
    {
        if (position.line >= lines_.size())
        {
            return protocol::Range{ position, position };
        }

        const std::string& line = lines_[position.line];
        size_t bytePos = CharacterToByteOffset(line, position.character);

        // 找到单词边界
        size_t start = bytePos;
        while (start > 0 && IsWordChar(line[start - 1]))
        {
            --start;
        }

        size_t end = bytePos;
        while (end < line.length() && IsWordChar(line[end]))
        {
            ++end;
        }

        protocol::Range range;
        range.start.line = position.line;
        range.start.character = ByteOffsetToCharacter(line, start);
        range.end.line = position.line;
        range.end.character = ByteOffsetToCharacter(line, end);

        return range;
    }

    void Document::UpdateInternalState()
    {
        UpdateLines();
        UpdateLineOffsets();
    }

    void Document::UpdateLines()
    {
        lines_.clear();

        size_t start = 0;
        for (size_t i = 0; i < item_.text.length(); ++i)
        {
            if (item_.text[i] == '\n')
            {
                lines_.push_back(item_.text.substr(start, i - start));
                start = i + 1;
            }
            else if (item_.text[i] == '\r')
            {
                if (i + 1 < item_.text.length() && item_.text[i + 1] == '\n')
                {
                    lines_.push_back(item_.text.substr(start, i - start));
                    start = i + 2;
                    ++i; // Skip \n
                }
                else
                {
                    lines_.push_back(item_.text.substr(start, i - start));
                    start = i + 1;
                }
            }
        }

        // 添加最后一行
        if (start <= item_.text.length())
        {
            lines_.push_back(item_.text.substr(start));
        }
    }

    void Document::UpdateLineOffsets()
    {
        line_offsets_.clear();
        line_offsets_.reserve(lines_.size() + 1);

        size_t offset = 0;
        line_offsets_.push_back(0);

        for (size_t i = 0; i < item_.text.length(); ++i)
        {
            if (item_.text[i] == '\n')
            {
                line_offsets_.push_back(i + 1);
            }
            else if (item_.text[i] == '\r')
            {
                if (i + 1 < item_.text.length() && item_.text[i + 1] == '\n')
                {
                    line_offsets_.push_back(i + 2);
                    ++i;
                }
                else
                {
                    line_offsets_.push_back(i + 1);
                }
            }
        }
    }

    bool Document::IsWordChar(char c) const
    {
        return std::isalnum(static_cast<unsigned char>(c)) || c == '_' || c == '$';
    }

    size_t Document::CharacterToByteOffset(const std::string& line, int32_t character) const
    {
        if (encoding_ == protocol::PositionEncodingKindLiterals::UTF8)
        {
            return std::min(static_cast<size_t>(character), line.length());
        }

        // UTF-16 编码：需要正确计算
        size_t byteOffset = 0;
        int32_t charCount = 0;

        while (byteOffset < line.length() && charCount < character)
        {
            unsigned char c = line[byteOffset];

            if (encoding_ == protocol::PositionEncodingKindLiterals::UTF16)
            {
                // UTF-16: 计算代码单元
                if ((c & 0x80) == 0)
                {
                    // ASCII
                    byteOffset += 1;
                    charCount += 1;
                }
                else if ((c & 0xE0) == 0xC0)
                {
                    // 2字节UTF-8 -> 1个UTF-16单元
                    byteOffset += 2;
                    charCount += 1;
                }
                else if ((c & 0xF0) == 0xE0)
                {
                    // 3字节UTF-8 -> 1个UTF-16单元
                    byteOffset += 3;
                    charCount += 1;
                }
                else if ((c & 0xF8) == 0xF0)
                {
                    // 4字节UTF-8 -> 2个UTF-16单元（代理对）
                    byteOffset += 4;
                    charCount += 2;
                }
                else
                {
                    byteOffset += 1; // 错误情况
                }
            }
            else // UTF32
            {
                // UTF-32: 每个Unicode代码点算一个
                if ((c & 0x80) == 0)
                {
                    byteOffset += 1;
                }
                else if ((c & 0xE0) == 0xC0)
                {
                    byteOffset += 2;
                }
                else if ((c & 0xF0) == 0xE0)
                {
                    byteOffset += 3;
                }
                else if ((c & 0xF8) == 0xF0)
                {
                    byteOffset += 4;
                }
                else
                {
                    byteOffset += 1;
                }
                charCount += 1;
            }
        }

        return byteOffset;
    }

    int32_t Document::ByteOffsetToCharacter(const std::string& line, size_t byteOffset) const
    {
        if (encoding_ == protocol::PositionEncodingKindLiterals::UTF8)
        {
            return static_cast<int32_t>(byteOffset);
        }

        int32_t charCount = 0;
        size_t pos = 0;

        while (pos < byteOffset && pos < line.length())
        {
            unsigned char c = line[pos];

            if (encoding_ == protocol::PositionEncodingKindLiterals::UTF16)
            {
                if ((c & 0x80) == 0)
                {
                    pos += 1;
                    charCount += 1;
                }
                else if ((c & 0xE0) == 0xC0)
                {
                    pos += 2;
                    charCount += 1;
                }
                else if ((c & 0xF0) == 0xE0)
                {
                    pos += 3;
                    charCount += 1;
                }
                else if ((c & 0xF8) == 0xF0)
                {
                    pos += 4;
                    charCount += 2; // 代理对
                }
                else
                {
                    pos += 1;
                    charCount += 1;
                }
            }
            else // UTF32
            {
                if ((c & 0x80) == 0)
                {
                    pos += 1;
                }
                else if ((c & 0xE0) == 0xC0)
                {
                    pos += 2;
                }
                else if ((c & 0xF0) == 0xE0)
                {
                    pos += 3;
                }
                else if ((c & 0xF8) == 0xF0)
                {
                    pos += 4;
                }
                else
                {
                    pos += 1;
                }
                charCount += 1;
            }
        }

        return charCount;
    }

    // ===== DocumentManager 实现 =====

    void DocumentManager::DidOpenTextDocument(const protocol::DidOpenTextDocumentParams& params)
    {
        std::unique_lock lock(mutex_);

        // 检查文档大小
        if (config_.max_document_size > 0 &&
            params.textDocument.text.length() > config_.max_document_size)
        {
            spdlog::error("Document {} exceeds maximum size ({} > {})",
                          params.textDocument.uri,
                          params.textDocument.text.length(),
                          config_.max_document_size);
            return;
        }

        // 创建新文档
        auto doc = std::make_shared<Document>(params.textDocument);
        doc->SetEncoding(config_.default_encoding);

        documents_[params.textDocument.uri] = doc;

        spdlog::info("Opened document: {} (version {}, {} bytes, language: {})",
                     params.textDocument.uri,
                     params.textDocument.version,
                     params.textDocument.text.length(),
                     params.textDocument.languageId);
    }

    void DocumentManager::DidChangeTextDocument(const protocol::DidChangeTextDocumentParams& params)
    {
        std::unique_lock lock(mutex_);

        auto it = documents_.find(params.textDocument.uri);
        if (it == documents_.end())
        {
            spdlog::error("Attempt to change non-existent document: {}",
                          params.textDocument.uri);
            return;
        }

        auto& doc = it->second;

        // 版本检查
        if (params.textDocument.version)
        {
            protocol::integer expectedVersion = params.textDocument.version;
            if (expectedVersion <= doc->GetVersion())
            {
                spdlog::warn("Ignoring stale change for {}: version {} <= current {}",
                             params.textDocument.uri,
                             expectedVersion,
                             doc->GetVersion());
                return;
            }
        }

        // 应用变更
        if (params.contentChanges.empty())
        {
            spdlog::warn("Empty content changes for document: {}", params.textDocument.uri);
            return;
        }

        // 检查是全文还是增量
        if (params.contentChanges.size() == 1)
        {
            // 全文更新
            // doc->SetContent(params.textDocument.version(doc->GetVersion() + 1), params.contentChanges[0].text);
        }
        else
        {
            // 增量更新
            // doc->ApplyContentChanges( params.textDocument.version(doc->GetVersion() + 1), params.contentChanges);
        }

        spdlog::debug("Changed document: {} to version {} ({} changes)", params.textDocument.uri, doc->GetVersion(), params.contentChanges.size());
    }

    void DocumentManager::DidCloseTextDocument(const protocol::DidCloseTextDocumentParams& params)
    {
        std::unique_lock lock(mutex_);

        auto it = documents_.find(params.textDocument.uri);
        if (it == documents_.end())
        {
            spdlog::warn("Attempt to close non-existent document: {}",
                         params.textDocument.uri);
            return;
        }

        documents_.erase(it);
        spdlog::info("Closed document: {}", params.textDocument.uri);
    }

    void DocumentManager::DidSaveTextDocument(const protocol::DidSaveTextDocumentParams& params)
    {
        std::shared_lock lock(mutex_);

        auto it = documents_.find(params.textDocument.uri);
        if (it == documents_.end())
        {
            spdlog::warn("Attempt to save non-existent document: {}",
                         params.textDocument.uri);
            return;
        }

        it->second->SetDirty(false);

        // 如果保存通知包含文本，可以验证同步状态
        if (params.text.has_value())
        {
            if (params.text.value() != it->second->GetText())
            {
                spdlog::error("Document content mismatch on save for: {}", params.textDocument.uri);
            }
        }

        spdlog::info("Saved document: {}", params.textDocument.uri);
    }

    std::shared_ptr<Document> DocumentManager::GetDocument(const std::string& uri) const
    {
        std::shared_lock lock(mutex_);

        auto it = documents_.find(uri);
        if (it != documents_.end())
        {
            return it->second;
        }

        return nullptr;
    }

    std::vector<std::string> DocumentManager::GetAllUris() const
    {
        std::shared_lock lock(mutex_);

        std::vector<std::string> uris;
        uris.reserve(documents_.size());

        for (const auto& [uri, doc] : documents_)
        {
            uris.push_back(uri);
        }

        return uris;
    }

    std::vector<std::shared_ptr<Document>> DocumentManager::GetAllDocuments() const
    {
        std::shared_lock lock(mutex_);

        std::vector<std::shared_ptr<Document>> docs;
        docs.reserve(documents_.size());

        for (const auto& [uri, doc] : documents_)
        {
            docs.push_back(doc);
        }

        return docs;
    }

    std::vector<std::shared_ptr<Document>> DocumentManager::GetDocumentsByLanguage(
        const std::string& languageId) const
    {
        std::shared_lock lock(mutex_);

        std::vector<std::shared_ptr<Document>> docs;

        for (const auto& [uri, doc] : documents_)
        {
            if (doc->GetLanguageId() == languageId)
            {
                docs.push_back(doc);
            }
        }

        return docs;
    }

    bool DocumentManager::HasDocument(const std::string& uri) const
    {
        std::shared_lock lock(mutex_);
        return documents_.find(uri) != documents_.end();
    }

    size_t DocumentManager::GetDocumentCount() const
    {
        std::shared_lock lock(mutex_);
        return documents_.size();
    }

    std::vector<std::string> DocumentManager::GetDirtyDocuments() const
    {
        std::shared_lock lock(mutex_);

        std::vector<std::string> dirtyUris;

        for (const auto& [uri, doc] : documents_)
        {
            if (doc->IsDirty())
            {
                dirtyUris.push_back(uri);
            }
        }

        return dirtyUris;
    }

    std::string DocumentManager::ResolveUri(const std::string& uri) const
    {
        // 如果已经是绝对URI，直接返回
        if (utils::IsFileUri(uri))
        {
            return uri;
        }

        // 尝试相对于工作区文件夹解析
        for (const auto& folder : workspace_folders_)
        {
            std::string folderPath = utils::UriToPath(folder.uri);
            std::string resolvedPath = folderPath + "/" + uri;

            // 检查文件是否存在（这里简化处理）
            return utils::PathToUri(resolvedPath);
        }

        return uri;
    }

    // ===== 工具函数实现 =====

    namespace utils
    {
        std::string NormalizeUri(const std::string& uri)
        {
            std::string normalized = uri;

            // 确保使用正斜杠
            std::replace(normalized.begin(), normalized.end(), '\\', '/');

            // 移除重复的斜杠
            auto newEnd = std::unique(normalized.begin(), normalized.end(), [](char a, char b) { return a == '/' && b == '/'; });
            normalized.erase(newEnd, normalized.end());

            return normalized;
        }

        std::string UriToPath(const std::string& uri)
        {
            if (uri.substr(0, 7) == "file://")
            {
                std::string path = uri.substr(7);

// Windows路径处理
#ifdef _WIN32
                if (path.length() >= 3 && path[0] == '/' &&
                    std::isalpha(path[1]) && path[2] == ':')
                {
                    path = path.substr(1);
                }
#endif

                return path;
            }

            return uri;
        }

        std::string PathToUri(const std::string& path)
        {
            std::string uri = "file://";

#ifdef _WIN32
            // Windows路径
            if (path.length() >= 2 && std::isalpha(path[0]) && path[1] == ':')
            {
                uri += "/";
            }
#endif

            uri += path;
            return NormalizeUri(uri);
        }

        bool IsFileUri(const std::string& uri)
        {
            return uri.substr(0, 7) == "file://";
        }

        protocol::TextEdit CreateReplace(const protocol::Range& range, const std::string& newText)
        {
            protocol::TextEdit edit;
            edit.range = range;
            edit.newText = newText;
            return edit;
        }

        protocol::TextEdit CreateInsert(const protocol::Position& position, const std::string& text)
        {
            return CreateReplace(protocol::Range{ position, position }, text);
        }

        protocol::TextEdit CreateDelete(const protocol::Range& range)
        {
            return CreateReplace(range, "");
        }

        bool IsPositionInRange(const protocol::Position& position, const protocol::Range& range)
        {
            if (position.line < range.start.line || position.line > range.end.line)
            {
                return false;
            }

            if (position.line == range.start.line && position.character < range.start.character)
            {
                return false;
            }

            if (position.line == range.end.line && position.character >= range.end.character)
            {
                return false;
            }

            return true;
        }

        bool IsRangeOverlapping(const protocol::Range& a, const protocol::Range& b)
        {
            return !(a.end.line < b.start.line ||
                     (a.end.line == b.start.line && a.end.character <= b.start.character) ||
                     b.end.line < a.start.line ||
                     (b.end.line == a.start.line && b.end.character <= a.start.character));
        }

        protocol::Range ExtendRange(const protocol::Range& range, int32_t lines)
        {
            protocol::Range extended = range;
            extended.start.line = std::max(static_cast<std::int32_t>(0), static_cast<std::int32_t>(extended.start.line - lines));
            extended.end.line += lines;
            return extended;
        }

        std::string ApplyTextEdits(const std::string& text,
                                   const std::vector<protocol::TextEdit>& edits)
        {
            if (edits.empty())
            {
                return text;
            }

            // 排序编辑（从后向前，避免偏移问题）
            std::vector<protocol::TextEdit> sortedEdits = edits;
            std::sort(sortedEdits.begin(), sortedEdits.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;
            });

            // 创建临时文档来应用编辑
            protocol::TextDocumentItem tempItem;
            tempItem.uri = "temp://";
            tempItem.languageId = "";
            tempItem.version = 0;
            tempItem.text = text;

            Document tempDoc(tempItem);
            std::string result = text;

            for (const auto& edit : sortedEdits)
            {
                size_t start = tempDoc.PositionToOffset(edit.range.start);
                size_t end = tempDoc.PositionToOffset(edit.range.end);

                result = result.substr(0, start) + edit.newText + result.substr(end);

                // 更新临时文档
                tempDoc.SetContent(0, result);
            }

            return result;
        }
    }
}
