#include "verify_client.hpp"
#include <iostream>
#include <cassert>
#include <thread>
#include <chrono>

using namespace verify;

// 测试配置
const std::string BASE_URL = "https://gendan.xyz";
const std::string APP_KEY = "your_app_key"; // 需要替换为实际的appKey
const std::string TEST_USERNAME = "test_user_cpp";
const std::string TEST_PASSWORD = "test123456";
const std::string TEST_DEVICE_ID = "cpp_test_device_001";

class TestRunner {
public:
    void run() {
        std::cout << "========================================\n";
        std::cout << "验证平台SDK C++ 测试\n";
        std::cout << "========================================\n\n";

        // 初始化客户端
        testClientCreation();

        // 测试应用信息接口
        testAppInfo();

        // 测试用户注册和登录
        testUserRegistration();
        testUserLogin();

        // 测试账户接口
        if (!token_.empty()) {
            testAccount();
            testHeartbeat();
        }

        // 测试充值接口
        testRecharge();

        // 测试设备管理
        if (!token_.empty()) {
            testDeviceManagement();
        }

        // 测试云端数据
        if (!token_.empty()) {
            testCloudData();
        }

        std::cout << "\n========================================\n";
        std::cout << "所有测试完成!\n";
        std::cout << "========================================\n";
    }

private:
    std::unique_ptr<Client> client_;
    std::string token_;
    uint64_t userId_ = 0;

    void testClientCreation() {
        std::cout << "[测试] 客户端创建... ";
        try {
            client_ = std::make_unique<Client>(BASE_URL, APP_KEY);
            client_->setTimeout(30);
            std::cout << "通过\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
            throw;
        }
    }

    void testAppInfo() {
        std::cout << "[测试] 获取应用信息... ";
        try {
            AppConfig config = client_->getAppInfo();
            std::cout << "通过\n";
            std::cout << "  - 应用名称: " << config.name << "\n";
            std::cout << "  - 计费类型: " << config.billingType << "\n";
            std::cout << "  - 最大设备数: " << config.maxDevices << "\n";
            std::cout << "  - 心跳间隔: " << config.heartbeatInterval << "秒\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }

        std::cout << "[测试] 检查更新... ";
        try {
            VersionInfo version = client_->checkUpdate("1.0.0");
            std::cout << "通过\n";
            std::cout << "  - 有更新: " << (version.hasUpdate ? "是" : "否") << "\n";
            std::cout << "  - 最新版本: " << version.latestVersion << "\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }

        std::cout << "[测试] 获取公告列表... ";
        try {
            auto announcements = client_->getAnnouncements();
            std::cout << "通过 (共" << announcements.size() << "条公告)\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }
    }

    void testUserRegistration() {
        std::cout << "[测试] 用户注册... ";
        try {
            // 先尝试登录，如果用户存在则跳过注册
            try {
                auto result = client_->login(TEST_USERNAME, TEST_PASSWORD, TEST_DEVICE_ID);
                userId_ = result["user_id"].get<uint64_t>();
                token_ = result["token"].get<std::string>();
                std::cout << "用户已存在，跳过注册\n";
                return;
            } catch (...) {
                // 用户不存在，继续注册
            }

            userId_ = client_->registerUser(
                TEST_USERNAME,
                TEST_PASSWORD,
                TEST_DEVICE_ID,
                "C++测试设备",
                "windows",
                "instance_001"
            );
            std::cout << "通过 (用户ID: " << userId_ << ")\n";

            // 注册后登录
            auto result = client_->login(TEST_USERNAME, TEST_PASSWORD, TEST_DEVICE_ID);
            token_ = result["token"].get<std::string>();
        } catch (const ApiException& e) {
            std::cout << "API错误 [" << e.code() << "]: " << e.what() << "\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }
    }

    void testUserLogin() {
        std::cout << "[测试] 用户登录... ";
        try {
            auto result = client_->login(TEST_USERNAME, TEST_PASSWORD, TEST_DEVICE_ID);
            userId_ = result["user_id"].get<uint64_t>();
            token_ = result["token"].get<std::string>();
            std::cout << "通过\n";
            std::cout << "  - 用户ID: " << userId_ << "\n";
            std::cout << "  - Token: " << token_.substr(0, 30) << "...\n";
        } catch (const ApiException& e) {
            std::cout << "API错误 [" << e.code() << "]: " << e.what() << "\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }
    }

    void testAccount() {
        std::cout << "[测试] 获取账户信息... ";
        try {
            UserInfo info = client_->getAccount(userId_);
            std::cout << "通过\n";
            std::cout << "  - 用户名: " << info.username << "\n";
            std::cout << "  - 余额: " << info.balance << "\n";
            std::cout << "  - 状态: " << info.status << "\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }
    }

    void testHeartbeat() {
        std::cout << "[测试] 心跳上报... ";
        try {
            auto result = client_->heartbeat(userId_, TEST_DEVICE_ID, "instance_001");
            std::cout << "通过\n";
            if (result.contains("balance")) {
                std::cout << "  - 当前余额: " << result["balance"] << "\n";
            }
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }
    }

    void testRecharge() {
        std::cout << "[测试] 卡密充值 (使用无效卡密测试错误处理)... ";
        try {
            auto result = client_->recharge(TEST_USERNAME, "invalid_card_key_12345", TEST_DEVICE_ID);
            std::cout << "未预期的成功\n";
        } catch (const ApiException& e) {
            std::cout << "通过 (预期错误: " << e.what() << ")\n";
        } catch (const std::exception& e) {
            std::cout << "通过 (预期错误: " << e.what() << ")\n";
        }
    }

    void testDeviceManagement() {
        std::cout << "[测试] 获取设备列表... ";
        try {
            auto devices = client_->getDevices();
            std::cout << "通过 (共" << devices.size() << "台设备)\n";
            for (const auto& d : devices) {
                std::cout << "  - 设备ID: " << d.deviceId << " (" << d.deviceName << ")\n";
            }
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }

        std::cout << "[测试] 获取设备数量... ";
        try {
            auto result = client_->getDeviceCount(userId_);
            std::cout << "通过\n";
            std::cout << "  - 已绑定: " << result["count"] << "\n";
            std::cout << "  - 最大数: " << result["max_devices"] << "\n";
            std::cout << "  - 剩余: " << result["remaining"] << "\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }

        std::cout << "[测试] 获取实例列表... ";
        try {
            auto instances = client_->getInstances(userId_);
            std::cout << "通过 (共" << instances.size() << "个实例)\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }
    }

    void testCloudData() {
        std::cout << "[测试] 获取云端常量... ";
        try {
            auto constants = client_->getConstants();
            std::cout << "通过 (共" << constants.size() << "个常量)\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }

        std::cout << "[测试] 获取云端变量... ";
        try {
            auto variables = client_->getVariables();
            std::cout << "通过 (共" << variables.size() << "个变量)\n";
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }
    }
};

// 加密测试
void testCrypto() {
    std::cout << "\n[测试] 加密功能...\n";

    // AES测试
    {
        std::cout << "  [AES加密/解密] ";
        try {
            Crypto aes(EncryptType::AES, "test_key_12345678");
            std::string plaintext = "Hello, World! 你好，世界！";
            std::string encrypted = aes.encrypt(plaintext);
            std::string decrypted = aes.decrypt(encrypted);

            if (decrypted == plaintext) {
                std::cout << "通过\n";
                std::cout << "    原文: " << plaintext << "\n";
                std::cout << "    密文: " << encrypted.substr(0, 50) << "...\n";
            } else {
                std::cout << "失败: 解密结果不匹配\n";
            }
        } catch (const CryptoException& e) {
            std::cout << "失败: " << e.what() << "\n";
            std::cout << "  提示: 请使用 -DUSE_OPENSSL 编译以启用AES加密\n";
        }
    }

    // RC4测试
    {
        std::cout << "  [RC4加密/解密] ";
        try {
            Crypto rc4(EncryptType::RC4, "rc4_secret_key");
            std::string plaintext = "Test RC4 encryption";
            std::string encrypted = rc4.encrypt(plaintext);
            std::string decrypted = rc4.decrypt(encrypted);

            if (decrypted == plaintext) {
                std::cout << "通过\n";
            } else {
                std::cout << "失败: 解密结果不匹配\n";
            }
        } catch (const std::exception& e) {
            std::cout << "失败: " << e.what() << "\n";
        }
    }
}

// 性能测试
void testPerformance() {
    std::cout << "\n[测试] 性能测试...\n";

    Client client(BASE_URL, APP_KEY);
    client.setTimeout(10);

    int successCount = 0;
    int failCount = 0;
    const int iterations = 10;

    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < iterations; ++i) {
        try {
            client.getAppInfo();
            ++successCount;
        } catch (...) {
            ++failCount;
        }
    }

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

    std::cout << "  - 请求次数: " << iterations << "\n";
    std::cout << "  - 成功次数: " << successCount << "\n";
    std::cout << "  - 失败次数: " << failCount << "\n";
    std::cout << "  - 总耗时: " << duration.count() << "ms\n";
    std::cout << "  - 平均耗时: " << (duration.count() / iterations) << "ms/请求\n";
}

int main(int argc, char* argv[]) {
    std::cout << R"(
╔════════════════════════════════════════════════════════════╗
║         验证平台 SDK C++ 测试程序                          ║
║         Verify Platform SDK C++ Test                       ║
╚════════════════════════════════════════════════════════════╝
)" << "\n";

    // 解析命令行参数
    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];
        if (arg == "--help" || arg == "-h") {
            std::cout << "用法: " << argv[0] << " [选项]\n";
            std::cout << "选项:\n";
            std::cout << "  --help, -h     显示帮助信息\n";
            std::cout << "  --crypto       仅测试加密功能\n";
            std::cout << "  --perf         仅测试性能\n";
            return 0;
        }
    }

    try {
        // 测试加密
        testCrypto();

        // 主测试
        TestRunner runner;
        runner.run();

        // 性能测试
        testPerformance();

    } catch (const std::exception& e) {
        std::cerr << "\n错误: " << e.what() << "\n";
        return 1;
    }

    return 0;
}
