#include "transformer_test.hpp"
#include "../../src/protocol/transform/transformer.hpp"
#include "../../src/protocol/transform/common.hpp"
#include "../../src/protocol/detail/basic_types.hpp"
#include <vector>
#include <map>
#include <optional>

namespace lsp::test
{
    void TransformerTests::registerTests(TestRunner& runner)
    {
        // ToLSPAny 基本类型
        runner.addTest("Transformer - ToLSPAny Boolean", testToLSPAnyBoolean);
        runner.addTest("Transformer - ToLSPAny Integer", testToLSPAnyInteger);
        runner.addTest("Transformer - ToLSPAny UInteger", testToLSPAnyUInteger);
        runner.addTest("Transformer - ToLSPAny Float", testToLSPAnyFloat);
        runner.addTest("Transformer - ToLSPAny Double", testToLSPAnyDouble);
        runner.addTest("Transformer - ToLSPAny String", testToLSPAnyString);
        runner.addTest("Transformer - ToLSPAny CString", testToLSPAnyCString);

        // ToLSPAny 容器类型
        runner.addTest("Transformer - ToLSPAny Vector", testToLSPAnyVector);
        runner.addTest("Transformer - ToLSPAny Map", testToLSPAnyMap);
        runner.addTest("Transformer - ToLSPAny Optional (有值)", testToLSPAnyOptionalValue);
        runner.addTest("Transformer - ToLSPAny Optional (nullopt)", testToLSPAnyOptionalNullopt);

        // ToLSPAny LSP类型
        runner.addTest("Transformer - ToLSPAny LSPObject", testToLSPAnyLSPObject);
        runner.addTest("Transformer - ToLSPAny LSPArray", testToLSPAnyLSPArray);
        runner.addTest("Transformer - ToLSPAny LSPAny", testToLSPAnyLSPAny);

        // FromLSPAny 基本类型
        runner.addTest("Transformer - FromLSPAny Boolean", testFromLSPAnyBoolean);
        runner.addTest("Transformer - FromLSPAny Integer", testFromLSPAnyInteger);
        runner.addTest("Transformer - FromLSPAny String", testFromLSPAnyString);
        runner.addTest("Transformer - FromLSPAny Double", testFromLSPAnyDouble);

        // FromLSPAny 容器类型
        runner.addTest("Transformer - FromLSPAny Vector", testFromLSPAnyVector);
        runner.addTest("Transformer - FromLSPAny Optional (有值)", testFromLSPAnyOptionalValue);
        runner.addTest("Transformer - FromLSPAny Optional (null)", testFromLSPAnyOptionalNull);
        runner.addTest("Transformer - FromLSPAny LSPObject", testFromLSPAnyLSPObject);
        runner.addTest("Transformer - FromLSPAny LSPArray", testFromLSPAnyLSPArray);

        // 数字类型转换
        runner.addTest("Transformer - 提取Integer", testExtractNumberFromInteger);
        runner.addTest("Transformer - 提取UInteger", testExtractNumberFromUInteger);
        runner.addTest("Transformer - 提取Decimal", testExtractNumberFromDecimal);
        runner.addTest("Transformer - 跨类型数字提取", testExtractNumberCrossType);

        // 错误处理
        runner.addTest("Transformer - 类型不匹配错误", testFromLSPAnyTypeMismatch);
        runner.addTest("Transformer - 无效数字错误", testFromLSPAnyInvalidNumber);
        runner.addTest("Transformer - 无效数组错误", testFromLSPAnyInvalidArray);

        // 嵌套结构
        runner.addTest("Transformer - 嵌套Vector", testNestedVector);
        runner.addTest("Transformer - 嵌套LSPObject", testNestedLSPObject);
        runner.addTest("Transformer - 混合类型嵌套", testMixedTypeNesting);
    }

    // ==================== ToLSPAny 基本类型测试 ====================

    TestResult TransformerTests::testToLSPAnyBoolean()
    {
        TestResult result;
        result.passed = true;

        auto any = transform::LSPAnyConverter::ToLSPAny(true);
        assertTrue(any.Is<protocol::boolean>(), "应该转换为boolean类型");
        assertEqual(true, any.Get<protocol::boolean>(), "值应该为true");

        auto any_false = transform::LSPAnyConverter::ToLSPAny(false);
        assertEqual(false, any_false.Get<protocol::boolean>(), "值应该为false");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyInteger()
    {
        TestResult result;
        result.passed = true;

        auto any = transform::LSPAnyConverter::ToLSPAny(42);
        assertTrue(any.Is<protocol::integer>(), "应该转换为integer类型");
        assertEqual(42, any.Get<protocol::integer>(), "值应该为42");

        auto any_negative = transform::LSPAnyConverter::ToLSPAny(-100);
        assertEqual(-100, any_negative.Get<protocol::integer>(), "负数应该正确转换");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyUInteger()
    {
        TestResult result;
        result.passed = true;

        auto any = transform::LSPAnyConverter::ToLSPAny(42u);
        assertTrue(any.Is<protocol::uinteger>(), "应该转换为uinteger类型");
        assertEqual(42u, any.Get<protocol::uinteger>(), "值应该为42");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyFloat()
    {
        TestResult result;
        result.passed = true;

        auto any = transform::LSPAnyConverter::ToLSPAny(3.14f);
        assertTrue(any.Is<protocol::decimal>(), "float应该转换为decimal类型");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyDouble()
    {
        TestResult result;
        result.passed = true;

        auto any = transform::LSPAnyConverter::ToLSPAny(2.718);
        assertTrue(any.Is<protocol::decimal>(), "应该转换为decimal类型");
        assertEqual(2.718, any.Get<protocol::decimal>(), "值应该为2.718");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyString()
    {
        TestResult result;
        result.passed = true;

        std::string str = "hello world";
        auto any = transform::LSPAnyConverter::ToLSPAny(str);
        assertTrue(any.Is<protocol::string>(), "应该转换为string类型");
        assertEqual(str, any.Get<protocol::string>(), "值应该为'hello world'");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyCString()
    {
        TestResult result;
        result.passed = true;

        auto any = transform::LSPAnyConverter::ToLSPAny("test");
        assertTrue(any.Is<protocol::string>(), "C字符串应该转换为string类型");
        assertEqual(std::string("test"), any.Get<protocol::string>(), "值应该为'test'");

        result.message = "成功";
        return result;
    }

    // ==================== ToLSPAny 容器类型测试 ====================

    TestResult TransformerTests::testToLSPAnyVector()
    {
        TestResult result;
        result.passed = true;

        std::vector<int> vec = { 1, 2, 3, 4, 5 };
        auto any = transform::LSPAnyConverter::ToLSPAny(vec);

        assertTrue(any.Is<protocol::LSPArray>(), "应该转换为LSPArray类型");
        const auto& arr = any.Get<protocol::LSPArray>();
        assertEqual(size_t(5), arr.size(), "数组大小应该为5");
        assertTrue(arr[0].Is<protocol::integer>(), "元素应该是integer类型");
        assertEqual(1, arr[0].Get<protocol::integer>(), "第一个元素应该为1");
        assertEqual(5, arr[4].Get<protocol::integer>(), "最后一个元素应该为5");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyMap()
    {
        TestResult result;
        result.passed = true;

        std::map<std::string, int> map = { { "a", 1 }, { "b", 2 }, { "c", 3 } };
        auto any = transform::LSPAnyConverter::ToLSPAny(map);

        assertTrue(any.Is<protocol::LSPObject>(), "应该转换为LSPObject类型");
        const auto& obj = any.Get<protocol::LSPObject>();
        assertEqual(size_t(3), obj.size(), "对象大小应该为3");
        assertTrue(obj.count("a") > 0, "应该包含键'a'");
        assertEqual(1, obj.at("a").Get<protocol::integer>(), "键'a'的值应该为1");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyOptionalValue()
    {
        TestResult result;
        result.passed = true;

        std::optional<int> opt = 100;
        auto any = transform::LSPAnyConverter::ToLSPAny(opt);

        assertTrue(any.Is<protocol::integer>(), "有值的optional应该转换为对应类型");
        assertEqual(100, any.Get<protocol::integer>(), "值应该为100");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyOptionalNullopt()
    {
        TestResult result;
        result.passed = true;

        std::optional<int> opt = std::nullopt;
        auto any = transform::LSPAnyConverter::ToLSPAny(opt);

        assertTrue(any.Is<std::nullptr_t>(), "nullopt应该转换为null");

        result.message = "成功";
        return result;
    }

    // ==================== ToLSPAny LSP类型测试 ====================

    TestResult TransformerTests::testToLSPAnyLSPObject()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPObject obj;
        obj["key"] = protocol::LSPAny(42);
        auto any = transform::LSPAnyConverter::ToLSPAny(obj);

        assertTrue(any.Is<protocol::LSPObject>(), "应该保持LSPObject类型");
        const auto& retrieved = any.Get<protocol::LSPObject>();
        assertEqual(size_t(1), retrieved.size(), "对象应该包含1个元素");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyLSPArray()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPArray arr;
        arr.push_back(protocol::LSPAny(1));
        arr.push_back(protocol::LSPAny(2));
        auto any = transform::LSPAnyConverter::ToLSPAny(arr);

        assertTrue(any.Is<protocol::LSPArray>(), "应该保持LSPArray类型");
        const auto& retrieved = any.Get<protocol::LSPArray>();
        assertEqual(size_t(2), retrieved.size(), "数组应该包含2个元素");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testToLSPAnyLSPAny()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny original(42);
        auto any = transform::LSPAnyConverter::ToLSPAny(original);

        assertTrue(any.Is<protocol::integer>(), "应该保持类型");
        assertEqual(42, any.Get<protocol::integer>(), "应该保持值");

        result.message = "成功";
        return result;
    }

    // ==================== FromLSPAny 基本类型测试 ====================

    TestResult TransformerTests::testFromLSPAnyBoolean()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(true);
        bool value = transform::LSPAnyConverter::FromLSPAny<bool>(any);
        assertEqual(true, value, "应该提取出true");

        protocol::LSPAny any_false(false);
        bool value_false = transform::LSPAnyConverter::FromLSPAny<bool>(any_false);
        assertEqual(false, value_false, "应该提取出false");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testFromLSPAnyInteger()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(42);
        int value = transform::LSPAnyConverter::FromLSPAny<int>(any);
        assertEqual(42, value, "应该提取出42");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testFromLSPAnyString()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any("test string");
        std::string value = transform::LSPAnyConverter::FromLSPAny<std::string>(any);
        assertEqual(std::string("test string"), value, "应该提取出'test string'");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testFromLSPAnyDouble()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(3.14159);
        double value = transform::LSPAnyConverter::FromLSPAny<double>(any);
        assertEqual(3.14159, value, "应该提取出3.14159");

        result.message = "成功";
        return result;
    }

    // ==================== FromLSPAny 容器类型测试 ====================

    TestResult TransformerTests::testFromLSPAnyVector()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPArray arr;
        arr.push_back(protocol::LSPAny(10));
        arr.push_back(protocol::LSPAny(20));
        arr.push_back(protocol::LSPAny(30));
        protocol::LSPAny any(arr);

        auto vec = transform::LSPAnyConverter::FromLSPAny<std::vector<int>>(any);
        assertEqual(size_t(3), vec.size(), "vector大小应该为3");
        assertEqual(10, vec[0], "第一个元素应该为10");
        assertEqual(20, vec[1], "第二个元素应该为20");
        assertEqual(30, vec[2], "第三个元素应该为30");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testFromLSPAnyOptionalValue()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(42);
        auto opt = transform::LSPAnyConverter::FromLSPAny<std::optional<int>>(any);

        assertTrue(opt.has_value(), "optional应该有值");
        assertEqual(42, opt.value(), "值应该为42");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testFromLSPAnyOptionalNull()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(nullptr);
        auto opt = transform::LSPAnyConverter::FromLSPAny<std::optional<int>>(any);

        assertFalse(opt.has_value(), "optional应该为nullopt");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testFromLSPAnyLSPObject()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPObject obj;
        obj["key1"] = protocol::LSPAny(100);
        obj["key2"] = protocol::LSPAny("value");
        protocol::LSPAny any(obj);

        auto retrieved = transform::LSPAnyConverter::FromLSPAny<protocol::LSPObject>(any);
        assertEqual(size_t(2), retrieved.size(), "对象应该有2个键");
        assertTrue(retrieved.count("key1") > 0, "应该包含key1");
        assertTrue(retrieved.count("key2") > 0, "应该包含key2");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testFromLSPAnyLSPArray()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPArray arr;
        arr.push_back(protocol::LSPAny(1));
        arr.push_back(protocol::LSPAny(2));
        protocol::LSPAny any(arr);

        auto retrieved = transform::LSPAnyConverter::FromLSPAny<protocol::LSPArray>(any);
        assertEqual(size_t(2), retrieved.size(), "数组应该有2个元素");

        result.message = "成功";
        return result;
    }

    // ==================== 数字类型转换测试 ====================

    TestResult TransformerTests::testExtractNumberFromInteger()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(static_cast<protocol::integer>(42));
        int value = transform::LSPAnyConverter::FromLSPAny<int>(any);
        assertEqual(42, value, "应该从integer提取出42");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testExtractNumberFromUInteger()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(static_cast<protocol::uinteger>(100));
        unsigned int value = transform::LSPAnyConverter::FromLSPAny<unsigned int>(any);
        assertEqual(100u, value, "应该从uinteger提取出100");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testExtractNumberFromDecimal()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(static_cast<protocol::decimal>(3.14));
        double value = transform::LSPAnyConverter::FromLSPAny<double>(any);
        assertEqual(3.14, value, "应该从decimal提取出3.14");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testExtractNumberCrossType()
    {
        TestResult result;
        result.passed = true;

        // integer -> double
        protocol::LSPAny int_any(42);
        double double_value = transform::LSPAnyConverter::FromLSPAny<double>(int_any);
        assertEqual(42.0, double_value, "integer应该能转换为double");

        // uinteger -> int
        protocol::LSPAny uint_any(100u);
        int int_value = transform::LSPAnyConverter::FromLSPAny<int>(uint_any);
        assertEqual(100, int_value, "uinteger应该能转换为int");

        result.message = "成功";
        return result;
    }

    // ==================== 错误处理测试 ====================

    TestResult TransformerTests::testFromLSPAnyTypeMismatch()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(42);

        try
        {
            // 尝试将integer提取为string应该抛出异常
            (void)transform::LSPAnyConverter::FromLSPAny<std::string>(any);
            result.passed = false;
            result.message = "应该抛出ConversionError异常";
        }
        catch (const transform::ConversionError& e)
        {
            // 预期的异常
            result.message = "成功";
        }
        catch (...)
        {
            result.passed = false;
            result.message = "抛出了错误的异常类型";
        }

        return result;
    }

    TestResult TransformerTests::testFromLSPAnyInvalidNumber()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any("not a number");

        try
        {
            // 尝试将string提取为int应该抛出异常
            (void)transform::LSPAnyConverter::FromLSPAny<int>(any);
            result.passed = false;
            result.message = "应该抛出ConversionError异常";
        }
        catch (const transform::ConversionError& e)
        {
            // 预期的异常
            result.message = "成功";
        }
        catch (...)
        {
            result.passed = false;
            result.message = "抛出了错误的异常类型";
        }

        return result;
    }

    TestResult TransformerTests::testFromLSPAnyInvalidArray()
    {
        TestResult result;
        result.passed = true;

        protocol::LSPAny any(42);

        try
        {
            // 尝试将integer提取为vector应该抛出异常
            (void)transform::LSPAnyConverter::FromLSPAny<std::vector<int>>(any);
            result.passed = false;
            result.message = "应该抛出ConversionError异常";
        }
        catch (const transform::ConversionError& e)
        {
            // 预期的异常
            result.message = "成功";
        }
        catch (...)
        {
            result.passed = false;
            result.message = "抛出了错误的异常类型";
        }

        return result;
    }

    // ==================== 嵌套结构测试 ====================

    TestResult TransformerTests::testNestedVector()
    {
        TestResult result;
        result.passed = true;

        std::vector<std::vector<int>> nested = { { 1, 2 }, { 3, 4, 5 } };
        auto any = transform::LSPAnyConverter::ToLSPAny(nested);

        assertTrue(any.Is<protocol::LSPArray>(), "应该转换为LSPArray");
        const auto& arr = any.Get<protocol::LSPArray>();
        assertEqual(size_t(2), arr.size(), "外层数组应该有2个元素");
        assertTrue(arr[0].Is<protocol::LSPArray>(), "第一个元素应该是LSPArray");

        auto result_vec = transform::LSPAnyConverter::FromLSPAny<std::vector<std::vector<int>>>(any);
        assertEqual(size_t(2), result_vec.size(), "应该有2个子vector");
        assertEqual(size_t(2), result_vec[0].size(), "第一个子vector应该有2个元素");
        assertEqual(1, result_vec[0][0], "第一个元素应该为1");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testNestedLSPObject()
    {
        TestResult result;
        result.passed = true;

        // 直接使用 LSPObject 创建嵌套结构：{"outer": {"inner": 42}}
        protocol::LSPObject innerObj;
        innerObj["inner"] = protocol::LSPAny(42);

        protocol::LSPObject outerObj;
        outerObj["outer"] = protocol::LSPAny(innerObj);

        auto any = transform::LSPAnyConverter::ToLSPAny(outerObj);
        assertTrue(any.Is<protocol::LSPObject>(), "应该保持为LSPObject");

        // 提取为 LSPObject，然后手动检查嵌套值
        auto result_obj = transform::LSPAnyConverter::FromLSPAny<protocol::LSPObject>(any);
        assertTrue(result_obj.count("outer") > 0, "应该包含'outer'键");
        assertTrue(result_obj.at("outer").Is<protocol::LSPObject>(), "'outer'应该是LSPObject");

        const auto& inner_obj = result_obj.at("outer").Get<protocol::LSPObject>();
        assertTrue(inner_obj.count("inner") > 0, "应该包含'inner'键");
        assertEqual(42, inner_obj.at("inner").Get<protocol::integer>(), "嵌套值应该为42");

        result.message = "成功";
        return result;
    }

    TestResult TransformerTests::testMixedTypeNesting()
    {
        TestResult result;
        result.passed = true;

        // 直接使用 LSPArray 和 LSPObject 创建混合嵌套结构
        protocol::LSPArray arr;
        arr.push_back(protocol::LSPAny(1));
        arr.push_back(protocol::LSPAny(nullptr)); // 表示 nullopt
        arr.push_back(protocol::LSPAny(3));

        protocol::LSPObject obj;
        obj["data"] = protocol::LSPAny(arr);

        auto any = transform::LSPAnyConverter::ToLSPAny(obj);
        assertTrue(any.Is<protocol::LSPObject>(), "应该保持为LSPObject");

        const auto& retrieved_obj = any.Get<protocol::LSPObject>();
        const auto& retrieved_arr = retrieved_obj.at("data").Get<protocol::LSPArray>();
        assertEqual(size_t(3), retrieved_arr.size(), "数组应该有3个元素");
        assertTrue(retrieved_arr[0].Is<protocol::integer>(), "第一个元素应该是integer");
        assertTrue(retrieved_arr[1].Is<std::nullptr_t>(), "第二个元素应该是null");
        assertTrue(retrieved_arr[2].Is<protocol::integer>(), "第三个元素应该是integer");

        result.message = "成功";
        return result;
    }

} // namespace lsp::test
