#pragma once

namespace lsp::transform
{
    // ==================== ToLSPAny 实现 ====================

    template<typename T>
    inline protocol::LSPAny LSPAnyConverter::ToLSPAny(const T& value)
    {
        using Type = std::decay_t<T>;

        // LSPAny 直接返回
        if constexpr (std::is_same_v<Type, protocol::LSPAny>)
        {
            return value;
        }
        // LSPObject 直接返回
        else if constexpr (std::is_same_v<Type, protocol::LSPObject>)
        {
            return protocol::LSPAny(value);
        }
        // LSPArray 直接返回
        else if constexpr (std::is_same_v<Type, protocol::LSPArray>)
        {
            return protocol::LSPAny(value);
        }
        else if constexpr (std::is_same_v<Type, const char*> ||
                           std::is_same_v<Type, char*>)
        {
            return protocol::LSPAny(protocol::string(value));
        }
        // LSP 基本类型（boolean, string, decimal, nullptr）
        else if constexpr (is_lsp_basic_type_v<Type>)
        {
            return protocol::LSPAny(value);
        }
        // 整数类型（依赖 LSPAny 模板构造函数）
        else if constexpr (std::is_integral_v<Type> &&
                           !std::is_same_v<Type, bool>)
        {
            return protocol::LSPAny(value);
        }
        // 浮点类型
        else if constexpr (std::is_floating_point_v<Type>)
        {
            return protocol::LSPAny(value);
        }
        // vector → LSPArray
        else if constexpr (is_vector_v<Type>)
        {
            protocol::LSPArray arr;
            arr.reserve(value.size());
            for (const auto& item : value)
                arr.push_back(ToLSPAny(item));
            return protocol::LSPAny(std::move(arr));
        }
        // map → LSPObject
        else if constexpr (is_map_v<Type>)
        {
            protocol::LSPObject obj;
            for (const auto& [key, val] : value)
                obj[key] = ToLSPAny(val);
            return protocol::LSPAny(std::move(obj));
        }
        // optional → LSPAny or null
        else if constexpr (is_optional_v<Type>)
        {
            if (value.has_value())
                return ToLSPAny(*value);
            return protocol::LSPAny(nullptr);
        }
        // 用户结构体 → LSPAny (通过 JSON)
        else if constexpr (is_user_struct_v<Type>)
        {
            return SerializeViaJson(value);
        }
        else
        {
            static_assert(!sizeof(Type), "Unsupported type for ToLSPAny");
        }
    }

    // ==================== FromLSPAny 实现 ====================

    template<typename T>
    inline T LSPAnyConverter::FromLSPAny(const protocol::LSPAny& any)
    {
        using Type = std::decay_t<T>;

        // LSPAny 直接返回
        if constexpr (std::is_same_v<Type, protocol::LSPAny>)
        {
            return any;
        }
        // LSPObject 提取
        else if constexpr (std::is_same_v<Type, protocol::LSPObject>)
        {
            if (!any.Is<protocol::LSPObject>())
                throw ConversionError("LSPAny does not contain LSPObject");
            return any.Get<protocol::LSPObject>();
        }
        // LSPArray 提取
        else if constexpr (std::is_same_v<Type, protocol::LSPArray>)
        {
            if (!any.Is<protocol::LSPArray>())
                throw ConversionError("LSPAny does not contain LSPArray");
            return any.Get<protocol::LSPArray>();
        }
        // boolean 提取
        else if constexpr (std::is_same_v<Type, bool>)
        {
            if (!any.Is<protocol::boolean>())
                throw ConversionError("LSPAny does not contain a boolean");
            return any.Get<protocol::boolean>();
        }
        // string 提取
        else if constexpr (std::is_same_v<Type, protocol::string> ||
                           std::is_same_v<Type, std::string>)
        {
            if (!any.Is<protocol::string>())
                throw ConversionError("LSPAny does not contain a string");
            return any.Get<protocol::string>();
        }
        // 数字类型提取
        else if constexpr (std::is_arithmetic_v<Type> &&
                           !std::is_same_v<Type, bool>)
        {
            return ExtractNumber<Type>(any);
        }
        // vector 提取
        else if constexpr (is_vector_v<Type>)
        {
            if (!any.Is<protocol::LSPArray>())
                throw ConversionError("LSPAny does not contain an array");

            const auto& arr = any.Get<protocol::LSPArray>();
            Type result;
            result.reserve(arr.size());
            for (const auto& item : arr)
                result.push_back(FromLSPAny<typename Type::value_type>(item));
            return result;
        }
        // map 提取
        else if constexpr (is_map_v<Type>)
        {
            if (!any.Is<protocol::LSPObject>())
                throw ConversionError("LSPAny does not contain an object");

            const auto& obj = any.Get<protocol::LSPObject>();
            Type result;
            for (const auto& [key, val] : obj)
                result[key] = FromLSPAny<typename Type::mapped_type>(val);
            return result;
        }
        // optional 提取
        else if constexpr (is_optional_v<Type>)
        {
            if (any.Is<std::nullptr_t>())
                return std::nullopt;
            return FromLSPAny<typename Type::value_type>(any);
        }
        // 用户结构体提取（通过 JSON）
        else if constexpr (is_user_struct_v<Type>)
        {
            return ConvertViaJson<Type>(any);
        }
        else
        {
            static_assert(!sizeof(Type), "Unsupported type for FromLSPAny");
        }
    }

    // ==================== 辅助工具实现 ====================

    template<typename T>
    inline T LSPAnyConverter::ExtractNumber(const protocol::LSPAny& any)
    {
        if (any.Is<protocol::integer>())
        {
            return static_cast<T>(any.Get<protocol::integer>());
        }
        else if (any.Is<protocol::uinteger>())
        {
            return static_cast<T>(any.Get<protocol::uinteger>());
        }
        else if (any.Is<protocol::decimal>())
        {
            return static_cast<T>(any.Get<protocol::decimal>());
        }
        else
        {
            throw ConversionError("LSPAny does not contain a number (integer/uinteger/decimal)");
        }
    }

    template<typename T>
    inline T LSPAnyConverter::ConvertViaJson(const protocol::LSPAny& any)
    {
        try
        {
            // 序列化 LSPAny 为 JSON
            std::string json;
            auto ec = glz::write_json(any.value, json);
            if (ec)
                throw ConversionError("Failed to serialize LSPAny to JSON: " + std::string(glz::format_error(ec, json)));

            // 解析 JSON 到目标类型
            T result;
            ec = glz::read_json(result, json);
            if (ec)
                throw ConversionError("Failed to parse JSON to target type: " + std::string(glz::format_error(ec, json)));
            return result;
        }
        catch (const std::exception& e)
        {
            throw ConversionError("LSPAny to struct conversion failed: " + std::string(e.what()));
        }
    }

    template<typename T>
    inline protocol::LSPAny LSPAnyConverter::SerializeViaJson(const T& obj)
    {
        try
        {
            // 使用 glaze 序列化为 JSON 字符串
            std::string json;
            auto ec = glz::write_json(obj, json);
            if (ec)
                throw ConversionError("Failed to serialize struct to JSON: " + std::string(glz::format_error(ec, json)));

            // 直接解析为 LSPAny
            protocol::LSPAny result;
            ec = glz::read_json(result, json);
            if (ec)
                throw ConversionError("Failed to parse JSON to LSPAny: " + std::string(glz::format_error(ec, json)));

            return result;
        }
        catch (const std::exception& e)
        {
            throw ConversionError("struct to LSPAny conversion failed: " + std::string(e.what()));
        }
    }
}
