#pragma once
#include <string>
#include <vector>
#include <optional>
#include <chrono>
#include <shared_mutex>
#include <spdlog/spdlog.h>
#include "../protocol/protocol.hpp"

namespace lsp::services
{
    class Document
    {
    public:
        Document(const protocol::TextDocumentItem& item);

        const protocol::DocumentUri& GetUri() const { return item_.uri; }
        const protocol::string& GetLanguageId() const { return item_.languageId; }
        protocol::integer GetVersion() const { return item_.version; }
        const protocol::string& GetText() const { return item_.text; }
        const protocol::TextDocumentItem& GetItem() const { return item_; }

        protocol::TextDocumentIdentifier GetIdentifier() const
        {
            return protocol::TextDocumentIdentifier{item_.uri};
        }

        protocol::VersionedTextDocumentIdentifier GetVersionedIdentifier() const
        {
            protocol::VersionedTextDocumentIdentifier id;
            id.uri = item_.uri;
            id.version = item_.version;
            return id;
        }

                // ===== 位置和范围操作 =====
        size_t PositionToOffset(const protocol::Position& position) const;
        protocol::Position OffsetToPosition(size_t offset) const;
        std::string GetTextInRange(const protocol::Range& range) const;

        // 内容更新
        void SetContent(protocol::integer version, const protocol::string& new_text);
        void ApplyContentChange(protocol::integer version, const std::vector<protocol::TextDocumentContentChangeEvent>& changes);

        // 获取指定位置的字符
        std::optional<char> GetCharAt(const protocol::Position& position) const;

        // ===== 行操作 =====
        const std::vector<std::string>& GetLines() const { return lines_; }
        size_t GetLineCount() const { return lines_.size(); }
        std::string GetLine(size_t lineNumber) const;
        std::string GetLineAt(const protocol::Position& position) const;

        // ===== 单词和符号操作 =====
        std::string GetWordAt(const protocol::Position& position) const;
        protocol::Range GetWordRangeAt(const protocol::Position& position) const;

        // ===== 实用方法 =====
        // 创建一个Location
        protocol::Location CreateLocation(const protocol::Range& range) const
        {
            return protocol::Location{item_.uri, range};
        }

        // 创建一个TextDocumentPositionParams
        protocol::TextDocumentPositionParams CreatePositionParams(const protocol::Position& position) const
        {
            protocol::TextDocumentPositionParams params;
            params.textDocument = GetIdentifier();
            params.position = position;
            return params;
        }

        // ===== 元数据 =====
        // 文档是否被修改（相对于上次保存）
        bool IsDirty() const { return is_dirty_; }
        void SetDirty(bool dirty) { is_dirty_ = dirty; }

        // 最后修改时间
        std::chrono::system_clock::time_point GetLastModified() const { return last_modified_time_; }

        void SetEncoding(protocol::PositionEncodingKind encoding) { encoding_ = encoding; }
        protocol::PositionEncodingKind GetEncoding() const { return encoding_; }

    private:
        // 更新内部缓存
        void UpdateInternalState();
        void UpdateLines();
        void UpdateLineOffsets();

        // 辅助方法
        bool IsWordChar(char c) const;
        size_t CharacterToByteOffset(const std::string& line, std::int32_t character) const;
        std::int32_t ByteOffsetToCharacter(const std::string& line, size_t byteOffset) const;

        // 应用单个内容变更
        void ApplyContentChange(const protocol::TextDocumentContentChangeEvent& change);

    private:
        protocol::TextDocumentItem item_;

        // 缓存行的信息
        std::vector<std::string> lines_;
        std::vector<size_t> line_offsets_;

        bool is_dirty_ = false;
        std::chrono::system_clock::time_point last_modified_time_;
        protocol::PositionEncodingKind encoding_ = protocol::PositionEncodingKindLiterals::UTF16;
    };

        /**
     * 文档管理器 - 使用protocol类型作为接口
     */
    class DocumentManager
    {
    public:
        DocumentManager() = default;
        ~DocumentManager() = default;

        // 禁止拷贝
        DocumentManager(const DocumentManager&) = delete;
        DocumentManager& operator=(const DocumentManager&) = delete;

        // ===== 文档生命周期管理 - 直接使用protocol类型 =====

        // 处理 textDocument/didOpen
        void DidOpenTextDocument(const protocol::DidOpenTextDocumentParams& params);

        // 处理 textDocument/didChange
        void DidChangeTextDocument(const protocol::DidChangeTextDocumentParams& params);

        // 处理 textDocument/didClose
        void DidCloseTextDocument(const protocol::DidCloseTextDocumentParams& params);

        // 处理 textDocument/didSave
        void DidSaveTextDocument(const protocol::DidSaveTextDocumentParams& params);

        // ===== 文档访问 - 支持多种查询方式 =====

        // 通过URI获取
        std::shared_ptr<Document> GetDocument(const std::string& uri) const;

        // 通过标识符获取
        std::shared_ptr<Document> GetDocument(const protocol::TextDocumentIdentifier& identifier) const
        {
            return GetDocument(identifier.uri);
        }

        // 通过版本化标识符获取
        std::shared_ptr<Document> GetDocument(const protocol::VersionedTextDocumentIdentifier& identifier) const
        {
            auto doc = GetDocument(identifier.uri);
            if (doc && identifier.version && doc->GetVersion() != identifier.version)
            {
                spdlog::warn("Version mismatch for {}: expected {}, got {}", identifier.uri, identifier.version, doc->GetVersion());
            }
            return doc;
        }

        // 通过TextDocumentPositionParams获取
        std::shared_ptr<Document> GetDocument(const protocol::TextDocumentPositionParams& params) const
        {
            return GetDocument(params.textDocument);
        }

        // ===== 批量操作 =====
        std::vector<std::string> GetAllUris() const;
        std::vector<std::shared_ptr<Document>> GetAllDocuments() const;
        std::vector<std::shared_ptr<Document>> GetDocumentsByLanguage(const std::string& languageId) const;

        // ===== 查询 =====
        bool HasDocument(const std::string& uri) const;
        bool IsDocumentOpen(const protocol::TextDocumentIdentifier& identifier) const
        {
            return HasDocument(identifier.uri);
        }

        size_t GetDocumentCount() const;

        // ===== 诊断支持 =====
        // 获取需要诊断的文档（已修改的）
        std::vector<std::string> GetDirtyDocuments() const;

        // ===== 工作区支持 =====
        // 设置工作区文件夹（用于相对路径解析）
        void SetWorkspaceFolders(const std::vector<protocol::WorkspaceFolder>& folders)
        {
            workspace_folders_ = folders;
        }

        const std::vector<protocol::WorkspaceFolder>& GetWorkspaceFolders() const
        {
            return workspace_folders_;
        }

        // 解析相对URI
        std::string ResolveUri(const std::string& uri) const;

        // ===== 配置 =====
        struct Configuration {
            size_t max_document_size = 10 * 1024 * 1024;  // 10MB
            bool validate_utf8 = true;
            protocol::PositionEncodingKind default_encoding = protocol::PositionEncodingKindLiterals::UTF16;
        };

        void SetConfiguration(const Configuration& config) { config_ = config; }
        const Configuration& GetConfiguration() const { return config_; }

    private:
        mutable std::shared_mutex mutex_;
        std::unordered_map<std::string, std::shared_ptr<Document>> documents_;
        std::vector<protocol::WorkspaceFolder> workspace_folders_;
        Configuration config_;
    };

    // ===== 工具函数 =====
    namespace utils
    {
        // URI处理
        std::string NormalizeUri(const std::string& uri);
        std::string UriToPath(const std::string& uri);
        std::string PathToUri(const std::string& path);
        bool IsFileUri(const std::string& uri);

        // 创建TextEdit
        protocol::TextEdit CreateReplace(const protocol::Range& range, const std::string& newText);
        protocol::TextEdit CreateInsert(const protocol::Position& position, const std::string& text);
        protocol::TextEdit CreateDelete(const protocol::Range& range);

        // 范围操作
        bool IsPositionInRange(const protocol::Position& position, const protocol::Range& range);
        bool IsRangeOverlapping(const protocol::Range& a, const protocol::Range& b);
        protocol::Range ExtendRange(const protocol::Range& range, int32_t lines);

        // 应用编辑
        std::string ApplyTextEdits(const std::string& text, const std::vector<protocol::TextEdit>& edits);
    }
}
