using System.Text.Json;
using FsCheck;
using FsCheck.Xunit;
using HoneyBox.Admin.Business.Models.Config;
using Xunit;

namespace HoneyBox.Tests.Services;

/// <summary>
/// 微信支付 V3 配置属性测试
/// **Feature: wechat-pay-v3-upgrade**
/// </summary>
public class WechatPayV3ConfigPropertyTests
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNameCaseInsensitive = true,
        PropertyNamingPolicy = null, // 使用原始属性名
        WriteIndented = false
    };

    #region Property 1: 配置序列化 Round-Trip

    /// <summary>
    /// **Feature: wechat-pay-v3-upgrade, Property 1: 配置序列化 Round-Trip**
    /// *For any* 有效的 WeixinPayMerchant 配置对象（包含 V2 或 V3 字段），
    /// 序列化为 JSON 后再反序列化，应该得到与原始对象等价的配置。
    /// **Validates: Requirements 1.4, 1.5**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool WeixinPayMerchant_V3Config_RoundTrip_ShouldPreserveAllFields(
        NonEmptyString name,
        NonEmptyString mchId,
        NonEmptyString orderPrefix,
        NonEmptyString apiKey,
        NonEmptyString apiV3Key,
        NonEmptyString certSerialNo,
        NonEmptyString privateKeyPath,
        NonEmptyString wechatPublicKeyId,
        NonEmptyString wechatPublicKeyPath,
        bool isV3)
    {
        // 创建包含 V3 字段的配置
        var original = new WeixinPayMerchant
        {
            Name = name.Get,
            MchId = mchId.Get,
            OrderPrefix = orderPrefix.Get.Length >= 3 ? orderPrefix.Get.Substring(0, 3) : "ABC",
            ApiKey = apiKey.Get,
            IsEnabled = "1",
            PayVersion = isV3 ? "V3" : "V2",
            ApiV3Key = isV3 ? apiV3Key.Get : null,
            CertSerialNo = isV3 ? certSerialNo.Get : null,
            PrivateKeyPath = isV3 ? privateKeyPath.Get : null,
            WechatPublicKeyId = isV3 ? wechatPublicKeyId.Get : null,
            WechatPublicKeyPath = isV3 ? wechatPublicKeyPath.Get : null
        };

        // 序列化
        var json = JsonSerializer.Serialize(original, JsonOptions);

        // 反序列化
        var deserialized = JsonSerializer.Deserialize<WeixinPayMerchant>(json, JsonOptions);

        if (deserialized == null) return false;

        // 验证所有字段
        return original.Name == deserialized.Name &&
               original.MchId == deserialized.MchId &&
               original.OrderPrefix == deserialized.OrderPrefix &&
               original.ApiKey == deserialized.ApiKey &&
               original.IsEnabled == deserialized.IsEnabled &&
               original.PayVersion == deserialized.PayVersion &&
               original.ApiV3Key == deserialized.ApiV3Key &&
               original.CertSerialNo == deserialized.CertSerialNo &&
               original.PrivateKeyPath == deserialized.PrivateKeyPath &&
               original.WechatPublicKeyId == deserialized.WechatPublicKeyId &&
               original.WechatPublicKeyPath == deserialized.WechatPublicKeyPath;
    }

    /// <summary>
    /// **Feature: wechat-pay-v3-upgrade, Property 1: 配置序列化 Round-Trip**
    /// *For any* 有效的 WeixinPaySetting 配置对象（包含多个商户），
    /// 序列化为 JSON 后再反序列化，应该得到与原始对象等价的配置。
    /// **Validates: Requirements 1.4, 1.5**
    /// </summary>
    [Property(MaxTest = 100)]
    public bool WeixinPaySetting_RoundTrip_ShouldPreserveAllMerchants(PositiveInt seed)
    {
        // 创建包含多个商户的配置
        var merchantCount = (seed.Get % 3) + 1; // 1-3 个商户
        var merchants = new List<WeixinPayMerchant>();

        for (int i = 0; i < merchantCount; i++)
        {
            var isV3 = i % 2 == 0; // 交替 V2/V3
            merchants.Add(new WeixinPayMerchant
            {
                Name = $"商户{i + 1}",
                MchId = $"mch{seed.Get + i}",
                OrderPrefix = $"M{i:D2}",
                ApiKey = $"key{seed.Get + i}",
                IsEnabled = "1",
                PayVersion = isV3 ? "V3" : "V2",
                ApiV3Key = isV3 ? $"v3key{seed.Get + i}" : null,
                CertSerialNo = isV3 ? $"serial{seed.Get + i}" : null,
                PrivateKeyPath = isV3 ? $"certs/{seed.Get + i}/key.pem" : null,
                WechatPublicKeyId = isV3 ? $"pubkeyid{seed.Get + i}" : null,
                WechatPublicKeyPath = isV3 ? $"certs/{seed.Get + i}/pub.pem" : null
            });
        }

        var original = new WeixinPaySetting { Merchants = merchants };

        // 序列化
        var json = JsonSerializer.Serialize(original, JsonOptions);

        // 反序列化
        var deserialized = JsonSerializer.Deserialize<WeixinPaySetting>(json, JsonOptions);

        if (deserialized == null || deserialized.Merchants == null) return false;
        if (original.Merchants.Count != deserialized.Merchants.Count) return false;

        // 验证每个商户
        for (int i = 0; i < original.Merchants.Count; i++)
        {
            var orig = original.Merchants[i];
            var deser = deserialized.Merchants[i];

            if (orig.Name != deser.Name ||
                orig.MchId != deser.MchId ||
                orig.OrderPrefix != deser.OrderPrefix ||
                orig.ApiKey != deser.ApiKey ||
                orig.IsEnabled != deser.IsEnabled ||
                orig.PayVersion != deser.PayVersion ||
                orig.ApiV3Key != deser.ApiV3Key ||
                orig.CertSerialNo != deser.CertSerialNo ||
                orig.PrivateKeyPath != deser.PrivateKeyPath ||
                orig.WechatPublicKeyId != deser.WechatPublicKeyId ||
                orig.WechatPublicKeyPath != deser.WechatPublicKeyPath)
            {
                return false;
            }
        }

        return true;
    }

    /// <summary>
    /// **Feature: wechat-pay-v3-upgrade, Property 1: 配置序列化 Round-Trip**
    /// *For any* V2 配置，PayVersion 默认值应该是 "V2"。
    /// **Validates: Requirements 1.3**
    /// </summary>
    [Fact]
    public void WeixinPayMerchant_DefaultPayVersion_ShouldBeV2()
    {
        var merchant = new WeixinPayMerchant();
        Assert.Equal("V2", merchant.PayVersion);
    }

    /// <summary>
    /// **Feature: wechat-pay-v3-upgrade, Property 1: 配置序列化 Round-Trip**
    /// *For any* V3 配置 JSON，反序列化后应该正确读取所有 V3 字段。
    /// **Validates: Requirements 1.1, 1.2**
    /// </summary>
    [Fact]
    public void WeixinPayMerchant_V3JsonDeserialization_ShouldReadAllV3Fields()
    {
        var json = @"{
            ""name"": ""测试商户"",
            ""mch_id"": ""1738725801"",
            ""order_prefix"": ""MYH"",
            ""api_key"": ""v2key"",
            ""is_enabled"": ""1"",
            ""pay_version"": ""V3"",
            ""api_v3_key"": ""d1cxc0vXCUH2984901DxddPJMYqcwcnd"",
            ""cert_serial_no"": ""SERIAL123456"",
            ""private_key_path"": ""certs/1738725801/apiclient_key.pem"",
            ""wechat_public_key_id"": ""PUB_KEY_ID_0117387258012026012500291641000801"",
            ""wechat_public_key_path"": ""certs/1738725801/pub_key.pem""
        }";

        var merchant = JsonSerializer.Deserialize<WeixinPayMerchant>(json, JsonOptions);

        Assert.NotNull(merchant);
        Assert.Equal("测试商户", merchant.Name);
        Assert.Equal("1738725801", merchant.MchId);
        Assert.Equal("MYH", merchant.OrderPrefix);
        Assert.Equal("v2key", merchant.ApiKey);
        Assert.Equal("1", merchant.IsEnabled);
        Assert.Equal("V3", merchant.PayVersion);
        Assert.Equal("d1cxc0vXCUH2984901DxddPJMYqcwcnd", merchant.ApiV3Key);
        Assert.Equal("SERIAL123456", merchant.CertSerialNo);
        Assert.Equal("certs/1738725801/apiclient_key.pem", merchant.PrivateKeyPath);
        Assert.Equal("PUB_KEY_ID_0117387258012026012500291641000801", merchant.WechatPublicKeyId);
        Assert.Equal("certs/1738725801/pub_key.pem", merchant.WechatPublicKeyPath);
    }

    /// <summary>
    /// **Feature: wechat-pay-v3-upgrade, Property 1: 配置序列化 Round-Trip**
    /// *For any* V2 配置 JSON（不包含 V3 字段），反序列化后 V3 字段应该为 null。
    /// **Validates: Requirements 1.3**
    /// </summary>
    [Fact]
    public void WeixinPayMerchant_V2JsonDeserialization_ShouldHaveNullV3Fields()
    {
        var json = @"{
            ""name"": ""V2商户"",
            ""mch_id"": ""1234567890"",
            ""order_prefix"": ""ABC"",
            ""api_key"": ""v2key"",
            ""is_enabled"": ""1""
        }";

        var merchant = JsonSerializer.Deserialize<WeixinPayMerchant>(json, JsonOptions);

        Assert.NotNull(merchant);
        Assert.Equal("V2商户", merchant.Name);
        Assert.Equal("V2", merchant.PayVersion); // 默认值
        Assert.Null(merchant.ApiV3Key);
        Assert.Null(merchant.CertSerialNo);
        Assert.Null(merchant.PrivateKeyPath);
        Assert.Null(merchant.WechatPublicKeyId);
        Assert.Null(merchant.WechatPublicKeyPath);
    }

    #endregion
}
