using System.Text.Json;
using System.Text.Json.Serialization;
using HoneyBox.Model.Base;
using HoneyBox.Model.Models;
using HoneyBox.Model.Models.Order;
using HoneyBox.Model.Models.Goods;
using HoneyBox.Model.Models.Payment;
using HoneyBox.Model.Models.Lottery;
using Xunit;

namespace HoneyBox.Tests.Integration;

/// <summary>
/// API响应格式验证测试
/// 验证所有接口响应格式与PHP API一致
/// Requirements: 18.1-18.4
/// </summary>
public class ApiResponseFormatTests
{
    private readonly JsonSerializerOptions _jsonOptions;

    public ApiResponseFormatTests()
    {
        _jsonOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = null, // Use JsonPropertyName attributes
            WriteIndented = false
        };
    }

    #region ApiResponse Base Format Tests

    /// <summary>
    /// 验证ApiResponse基类使用正确的snake_case字段名
    /// Requirements: 18.1, 18.3
    /// </summary>
    [Fact]
    public void ApiResponse_ShouldUseCorrectFieldNames()
    {
        // Arrange
        var response = ApiResponse.Success("success");

        // Act
        var json = JsonSerializer.Serialize(response, _jsonOptions);

        // Assert
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"msg\":", json);
        Assert.DoesNotContain("\"Status\":", json);
        Assert.DoesNotContain("\"Msg\":", json);
    }

    /// <summary>
    /// 验证ApiResponse<T>包含data字段
    /// Requirements: 18.1, 18.3
    /// </summary>
    [Fact]
    public void ApiResponseGeneric_ShouldIncludeDataField()
    {
        // Arrange
        var response = ApiResponse<string>.Success("test data");

        // Act
        var json = JsonSerializer.Serialize(response, _jsonOptions);

        // Assert
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"msg\":", json);
        Assert.Contains("\"data\":", json);
        Assert.DoesNotContain("\"Data\":", json);
    }

    /// <summary>
    /// 验证成功响应status=1
    /// Requirements: 18.1
    /// </summary>
    [Fact]
    public void ApiResponse_Success_ShouldHaveStatus1()
    {
        // Arrange & Act
        var response = ApiResponse.Success();

        // Assert
        Assert.Equal(1, response.Status);
    }

    /// <summary>
    /// 验证失败响应status=0
    /// Requirements: 18.1
    /// </summary>
    [Fact]
    public void ApiResponse_Fail_ShouldHaveStatus0()
    {
        // Arrange & Act
        var response = ApiResponse.Fail("error");

        // Assert
        Assert.Equal(0, response.Status);
    }

    /// <summary>
    /// 验证未授权响应status=-1
    /// Requirements: 18.1
    /// </summary>
    [Fact]
    public void ApiResponse_Unauthorized_ShouldHaveStatusMinus1()
    {
        // Arrange & Act
        var response = ApiResponse.Unauthorized();

        // Assert
        Assert.Equal(-1, response.Status);
    }

    #endregion

    #region Order Models Format Tests

    /// <summary>
    /// 验证OrderMoneyRequest使用snake_case
    /// Requirements: 18.2
    /// </summary>
    [Fact]
    public void OrderMoneyRequest_ShouldUseSnakeCase()
    {
        // Arrange
        var request = new OrderMoneyRequest
        {
            GoodsId = 1,
            Num = 1,
            PrizeNum = 1,
            UseMoneyIs = 1,
            UseIntegralIs = 1,
            UseMoney2Is = 1
        };

        // Act
        var json = JsonSerializer.Serialize(request, _jsonOptions);

        // Assert
        Assert.Contains("\"goods_id\":", json);
        Assert.Contains("\"num\":", json);
        Assert.Contains("\"prize_num\":", json);
        Assert.Contains("\"use_money_is\":", json);
        Assert.Contains("\"use_integral_is\":", json);
        Assert.Contains("\"use_money2_is\":", json);
    }

    /// <summary>
    /// 验证OrderCalculationDto使用snake_case
    /// Requirements: 18.2
    /// </summary>
    [Fact]
    public void OrderCalculationDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new OrderCalculationDto
        {
            OrderTotal = "100.00",
            Price = "10.00",
            Money = "50.00",
            Integral = "100.00",
            Score = 20.00m,
            UseMoney = "10.00",
            UseIntegral = "5.00",
            UseMoney2 = 3.00m,
            CouponPrice = "2.00"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"order_total\":", json);
        Assert.Contains("\"price\":", json);
        Assert.Contains("\"money\":", json);
        Assert.Contains("\"integral\":", json);
        Assert.Contains("\"score\":", json);
        Assert.Contains("\"use_money\":", json);
        Assert.Contains("\"use_integral\":", json);
        Assert.Contains("\"coupon_price\":", json);
    }

    /// <summary>
    /// 验证OrderBuyResponseDto使用snake_case
    /// Requirements: 18.2
    /// </summary>
    [Fact]
    public void OrderBuyResponseDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new OrderBuyResponseDto
        {
            Status = 1,
            OrderNum = "TEST001"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"order_num\":", json);
        Assert.Contains("\"res\":", json);
    }

    /// <summary>
    /// 验证OrderListDto使用snake_case
    /// Requirements: 18.2
    /// </summary>
    [Fact]
    public void OrderListDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new OrderListDto
        {
            Id = 1,
            OrderNum = "TEST001",
            GoodsTitle = "Test",
            GoodsImgUrl = "http://test.com/img.jpg",
            OrderTotal = "100.00",
            Price = "100.00",
            PrizeNum = 1,
            Status = 1,
            AddTime = 1234567890,
            PayTime = 1234567890,
            OrderType = 1
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"order_num\":", json);
        Assert.Contains("\"goods_title\":", json);
        Assert.Contains("\"goods_imgurl\":", json);
        Assert.Contains("\"order_total\":", json);
        Assert.Contains("\"price\":", json);
        Assert.Contains("\"prize_num\":", json);
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"addtime\":", json);
        Assert.Contains("\"pay_time\":", json);
        Assert.Contains("\"order_type\":", json);
    }

    /// <summary>
    /// 验证PrizeOrderLogDto使用snake_case
    /// Requirements: 18.2
    /// </summary>
    [Fact]
    public void PrizeOrderLogDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new PrizeOrderLogDto
        {
            Id = 1,
            UserId = 1,
            GoodsListTitle = "Test",
            GoodsListImgUrl = "http://test.com/img.jpg",
            GoodsListPrice = "100.00",
            GoodsListMoney = "50.00",
            Status = 0,
            LuckNo = 1,
            ShangId = 1
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"user_id\":", json);
        Assert.Contains("\"goodslist_title\":", json);
        Assert.Contains("\"goodslist_imgurl\":", json);
        Assert.Contains("\"goodslist_price\":", json);
        Assert.Contains("\"goodslist_money\":", json);
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"luck_no\":", json);
        Assert.Contains("\"shang_id\":", json);
    }

    #endregion

    #region Warehouse Models Format Tests

    /// <summary>
    /// 验证WarehouseIndexRequest使用snake_case
    /// Requirements: 18.4
    /// </summary>
    [Fact]
    public void WarehouseIndexRequest_ShouldUseSnakeCase()
    {
        // Arrange
        var request = new WarehouseIndexRequest
        {
            Page = 1,
            PageSize = 10,
            Type = 1
        };

        // Act
        var json = JsonSerializer.Serialize(request, _jsonOptions);

        // Assert
        Assert.Contains("\"page\":", json);
        Assert.Contains("\"page_size\":", json);
        Assert.Contains("\"type\":", json);
    }

    /// <summary>
    /// 验证WarehouseItemDto使用snake_case
    /// Requirements: 18.4
    /// </summary>
    [Fact]
    public void WarehouseItemDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new WarehouseItemDto
        {
            Id = 1,
            GoodsListTitle = "Test",
            GoodsListImgUrl = "http://test.com/img.jpg",
            GoodsListPrice = "100.00",
            GoodsListMoney = "50.00",
            Status = 0,
            AddTime = 1234567890,
            ShangId = 1,
            GoodsId = 1
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"goodslist_title\":", json);
        Assert.Contains("\"goodslist_imgurl\":", json);
        Assert.Contains("\"goodslist_price\":", json);
        Assert.Contains("\"goodslist_money\":", json);
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"addtime\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"goods_id\":", json);
    }

    /// <summary>
    /// 验证RecoveryResultDto使用snake_case
    /// Requirements: 18.4
    /// </summary>
    [Fact]
    public void RecoveryResultDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new RecoveryResultDto
        {
            TotalMoney = "100.00",
            Count = 5,
            RecoveryNum = "REC001",
            UserMoney = "150.00"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"total_money\":", json);
        Assert.Contains("\"count\":", json);
        Assert.Contains("\"recovery_num\":", json);
        Assert.Contains("\"user_money\":", json);
    }

    /// <summary>
    /// 验证SendRecordDto使用snake_case
    /// Requirements: 18.4
    /// </summary>
    [Fact]
    public void SendRecordDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new SendRecordDto
        {
            Id = 1,
            SendNum = "SEND001",
            Name = "Test",
            Mobile = "138****0000",
            Address = "Test Address",
            Status = 1,
            StatusName = "待发货",
            Count = 3,
            Freight = "10.00",
            AddTime = "2024-01-01 12:00:00"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"send_num\":", json);
        Assert.Contains("\"name\":", json);
        Assert.Contains("\"mobile\":", json);
        Assert.Contains("\"address\":", json);
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"status_name\":", json);
        Assert.Contains("\"count\":", json);
        Assert.Contains("\"freight\":", json);
        Assert.Contains("\"addtime\":", json);
    }

    /// <summary>
    /// 验证LogisticsDto使用snake_case
    /// Requirements: 18.4
    /// </summary>
    [Fact]
    public void LogisticsDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new LogisticsDto
        {
            CourierNumber = "SF123456",
            CourierName = "顺丰速运",
            CourierCode = "SF",
            Count = 3,
            SendNum = "SEND001",
            DeliveryStatus = "已签收"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"courier_number\":", json);
        Assert.Contains("\"courier_name\":", json);
        Assert.Contains("\"courier_code\":", json);
        Assert.Contains("\"count\":", json);
        Assert.Contains("\"send_num\":", json);
        Assert.Contains("\"delivery_status\":", json);
    }

    #endregion

    #region PageResponse Format Tests

    /// <summary>
    /// 验证PageResponse使用snake_case
    /// Requirements: 18.2, 18.4
    /// </summary>
    [Fact]
    public void PageResponse_ShouldUseSnakeCase()
    {
        // Arrange
        var response = new PageResponse<OrderListDto>
        {
            Data = new List<OrderListDto>(),
            LastPage = 10,
            Total = 100,
            Page = 1,
            PageSize = 10
        };

        // Act
        var json = JsonSerializer.Serialize(response, _jsonOptions);

        // Assert
        Assert.Contains("\"data\":", json);
        Assert.Contains("\"last_page\":", json);
        Assert.Contains("\"total\":", json);
        Assert.Contains("\"page\":", json);
        Assert.Contains("\"page_size\":", json);
    }

    #endregion

    #region WechatPayParams Format Tests

    /// <summary>
    /// 验证WechatPayParamsDto使用正确的字段名（微信API要求的camelCase）
    /// Requirements: 18.2
    /// </summary>
    [Fact]
    public void WechatPayParamsDto_ShouldUseCamelCaseForWechatApi()
    {
        // Arrange
        var dto = new WechatPayParamsDto
        {
            AppId = "wx123456",
            TimeStamp = "1234567890",
            NonceStr = "abc123",
            Package = "prepay_id=xxx",
            SignType = "RSA",
            PaySign = "sign123"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert - 微信支付参数使用camelCase是正确的
        Assert.Contains("\"appId\":", json);
        Assert.Contains("\"timeStamp\":", json);
        Assert.Contains("\"nonceStr\":", json);
        Assert.Contains("\"package\":", json);
        Assert.Contains("\"signType\":", json);
        Assert.Contains("\"paySign\":", json);
    }

    #endregion

    #region Complete Response Serialization Tests

    /// <summary>
    /// 验证完整的订单金额计算响应格式
    /// Requirements: 18.1, 18.2
    /// </summary>
    [Fact]
    public void CompleteOrderCalculationResponse_ShouldMatchPhpFormat()
    {
        // Arrange
        var data = new OrderCalculationDto
        {
            OrderTotal = "100.00",
            Price = "10.00",
            Goods = new GoodsInfoDto { Id = 1, Title = "Test" },
            Money = "50.00",
            Integral = "100.00",
            Score = 20.00m
        };
        var response = ApiResponse<OrderCalculationDto>.Success(data);

        // Act
        var json = JsonSerializer.Serialize(response, _jsonOptions);

        // Assert - 验证顶层结构
        Assert.Contains("\"status\":1", json);
        Assert.Contains("\"msg\":\"success\"", json);
        Assert.Contains("\"data\":", json);

        // Assert - 验证数据字段
        Assert.Contains("\"order_total\":\"100.00\"", json);
        Assert.Contains("\"price\":\"10.00\"", json);
        Assert.Contains("\"goods\":", json);
        Assert.Contains("\"money\":\"50.00\"", json);
        Assert.Contains("\"integral\":\"100.00\"", json);
        Assert.Contains("\"score\":20", json);
    }

    /// <summary>
    /// 验证完整的仓库首页响应格式
    /// Requirements: 18.3, 18.4
    /// </summary>
    [Fact]
    public void CompleteWarehouseIndexResponse_ShouldMatchPhpFormat()
    {
        // Arrange
        var data = new WarehouseIndexResponseDto
        {
            Total = 100,
            Data = new List<WarehouseGoodsGroupDto>
            {
                new WarehouseGoodsGroupDto
                {
                    GoodsId = 1,
                    GoodsTitle = "Test",
                    OrderList = new List<WarehouseItemDto>
                    {
                        new WarehouseItemDto
                        {
                            Id = 1,
                            GoodsListTitle = "Prize",
                            GoodsListImgUrl = "http://test.com/img.jpg",
                            GoodsListPrice = "100.00",
                            GoodsListMoney = "50.00",
                            Status = 0
                        }
                    }
                }
            },
            LastPage = 10
        };
        var response = ApiResponse<WarehouseIndexResponseDto>.Success(data);

        // Act
        var json = JsonSerializer.Serialize(response, _jsonOptions);

        // Assert - 验证顶层结构
        Assert.Contains("\"status\":1", json);
        Assert.Contains("\"msg\":\"success\"", json);
        Assert.Contains("\"data\":", json);

        // Assert - 验证数据字段
        Assert.Contains("\"total\":", json);
        Assert.Contains("\"last_page\":", json);
        Assert.Contains("\"goods_id\":", json);
        Assert.Contains("\"goods_title\":", json);
        Assert.Contains("\"goodslist_title\":", json);
        Assert.Contains("\"goodslist_imgurl\":", json);
        Assert.Contains("\"goodslist_price\":", json);
        Assert.Contains("\"goodslist_money\":", json);
    }

    #endregion


    #region Payment System Response Format Tests - Requirements 10.1-10.4

    /// <summary>
    /// 验证WechatPayResult使用正确的字段名
    /// Requirements: 10.1, 10.3
    /// </summary>
    [Fact]
    public void WechatPayResult_ShouldUseCorrectFieldNames()
    {
        // Arrange
        var result = new WechatPayResult
        {
            Status = 1,
            Msg = "success",
            Data = new WechatPayData
            {
                AppId = "wx123456",
                TimeStamp = "1234567890",
                NonceStr = "abc123",
                Package = "prepay_id=xxx",
                SignType = "MD5",
                PaySign = "sign123",
                IsWeixin = 1
            }
        };

        // Act
        var json = JsonSerializer.Serialize(result, _jsonOptions);

        // Assert - 验证顶层结构使用snake_case
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"msg\":", json);
        Assert.Contains("\"data\":", json);
        Assert.DoesNotContain("\"Status\":", json);
        Assert.DoesNotContain("\"Msg\":", json);
        Assert.DoesNotContain("\"Data\":", json);
    }

    /// <summary>
    /// 验证WechatPayData使用正确的字段名（微信API要求的camelCase）
    /// Requirements: 10.2, 10.4
    /// </summary>
    [Fact]
    public void WechatPayData_ShouldUseCamelCaseForWechatApi()
    {
        // Arrange
        var data = new WechatPayData
        {
            AppId = "wx123456",
            TimeStamp = "1234567890",
            NonceStr = "abc123",
            Package = "prepay_id=xxx",
            SignType = "MD5",
            PaySign = "sign123",
            IsWeixin = 1
        };

        // Act
        var json = JsonSerializer.Serialize(data, _jsonOptions);

        // Assert - 微信支付参数使用camelCase（与PHP API一致）
        Assert.Contains("\"appId\":", json);
        Assert.Contains("\"timeStamp\":", json);
        Assert.Contains("\"nonceStr\":", json);
        Assert.Contains("\"package\":", json);
        Assert.Contains("\"signType\":", json);
        Assert.Contains("\"paySign\":", json);
        Assert.Contains("\"is_weixin\":", json); // is_weixin使用snake_case
    }

    /// <summary>
    /// 验证WechatPayResult成功响应status=1
    /// Requirements: 10.3
    /// </summary>
    [Fact]
    public void WechatPayResult_Success_ShouldHaveStatus1()
    {
        // Arrange
        var result = new WechatPayResult
        {
            Status = 1,
            Msg = "success",
            Data = new WechatPayData()
        };

        // Assert
        Assert.Equal(1, result.Status);
    }

    /// <summary>
    /// 验证WechatPayResult失败响应status=0
    /// Requirements: 10.3
    /// </summary>
    [Fact]
    public void WechatPayResult_Fail_ShouldHaveStatus0()
    {
        // Arrange
        var result = new WechatPayResult
        {
            Status = 0,
            Msg = "支付失败"
        };

        // Assert
        Assert.Equal(0, result.Status);
    }

    /// <summary>
    /// 验证WechatPayRequest使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void WechatPayRequest_ShouldUseSnakeCase()
    {
        // Arrange
        var request = new WechatPayRequest
        {
            OrderNo = "TEST001",
            Amount = 100.00m,
            Body = "商品购买",
            Attach = "order_yfs",
            OpenId = "openid123",
            UserId = 1
        };

        // Act
        var json = JsonSerializer.Serialize(request, _jsonOptions);

        // Assert
        Assert.Contains("\"order_no\":", json);
        Assert.Contains("\"amount\":", json);
        Assert.Contains("\"body\":", json);
        Assert.Contains("\"attach\":", json);
        Assert.Contains("\"open_id\":", json);
        Assert.Contains("\"user_id\":", json);
    }

    /// <summary>
    /// 验证PaymentRecordDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void PaymentRecordDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new HoneyBox.Model.Models.Payment.PaymentRecordDto
        {
            Id = 1,
            UserId = 1,
            OrderNum = "TEST001",
            ChangeMoney = "100.00",
            Content = "支付测试",
            PayType = 1,
            PayTypeText = "微信支付",
            CreatedAt = 1234567890
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"user_id\":", json);
        Assert.Contains("\"order_num\":", json);
        Assert.Contains("\"change_money\":", json);
        Assert.Contains("\"content\":", json);
        Assert.Contains("\"pay_type\":", json);
        Assert.Contains("\"pay_type_text\":", json);
        Assert.Contains("\"created_at\":", json);
    }

    /// <summary>
    /// 验证完整的微信支付响应格式与PHP API一致
    /// Requirements: 10.1-10.4
    /// </summary>
    [Fact]
    public void CompleteWechatPayResponse_ShouldMatchPhpFormat()
    {
        // Arrange - 模拟PHP API返回的格式
        // PHP: return ['status' => 1, 'data' => $res];
        // $res = ['appId' => ..., 'timeStamp' => ..., 'nonceStr' => ..., 'package' => ..., 'signType' => ..., 'paySign' => ...]
        var result = new WechatPayResult
        {
            Status = 1,
            Msg = "success",
            Data = new WechatPayData
            {
                AppId = "wx1234567890abcdef",
                TimeStamp = "1735776000",
                NonceStr = "abc123def456",
                Package = "prepay_id=wx123456789",
                SignType = "MD5",
                PaySign = "ABCDEF1234567890",
                IsWeixin = 1
            }
        };

        // Act
        var json = JsonSerializer.Serialize(result, _jsonOptions);

        // Assert - 验证顶层结构
        Assert.Contains("\"status\":1", json);
        Assert.Contains("\"msg\":\"success\"", json);
        Assert.Contains("\"data\":", json);

        // Assert - 验证支付参数字段名（与PHP一致）
        Assert.Contains("\"appId\":\"wx1234567890abcdef\"", json);
        Assert.Contains("\"timeStamp\":\"1735776000\"", json);
        Assert.Contains("\"nonceStr\":\"abc123def456\"", json);
        Assert.Contains("\"package\":\"prepay_id=wx123456789\"", json);
        Assert.Contains("\"signType\":\"MD5\"", json);
        Assert.Contains("\"paySign\":\"ABCDEF1234567890\"", json);
        Assert.Contains("\"is_weixin\":1", json);
    }

    /// <summary>
    /// 验证微信支付失败响应格式
    /// Requirements: 10.1, 10.3
    /// </summary>
    [Fact]
    public void WechatPayFailResponse_ShouldMatchPhpFormat()
    {
        // Arrange - 模拟PHP API返回的失败格式
        // PHP: return ['status' => 0, 'msg' => '支付失败'];
        var result = new WechatPayResult
        {
            Status = 0,
            Msg = "网络故障，请稍后重试(支付参数错误)"
        };

        // Act
        var json = JsonSerializer.Serialize(result, _jsonOptions);

        // Assert - 验证结构正确（不验证具体中文内容，因为JSON会转义Unicode）
        Assert.Contains("\"status\":0", json);
        Assert.Contains("\"msg\":", json);
        // data字段应该为null
        Assert.Contains("\"data\":null", json);
        
        // 验证反序列化后内容正确
        var deserialized = JsonSerializer.Deserialize<WechatPayResult>(json, _jsonOptions);
        Assert.NotNull(deserialized);
        Assert.Equal(0, deserialized.Status);
        Assert.Equal("网络故障，请稍后重试(支付参数错误)", deserialized.Msg);
    }

    /// <summary>
    /// 验证支付回调XML响应格式
    /// Requirements: 10.1
    /// </summary>
    [Fact]
    public void NotifyXmlResponse_ShouldMatchWechatFormat()
    {
        // Arrange - 微信要求的XML响应格式
        var successXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        var failXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>";

        // Assert - 验证XML格式正确
        Assert.Contains("<return_code><![CDATA[SUCCESS]]></return_code>", successXml);
        Assert.Contains("<return_msg><![CDATA[OK]]></return_msg>", successXml);
        Assert.Contains("<return_code><![CDATA[FAIL]]></return_code>", failXml);
    }

    #endregion

    #region Lottery System Response Format Tests - Requirements 10.1-10.4

    /// <summary>
    /// 验证PrizeOrderLogRequest使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void LotteryPrizeOrderLogRequest_ShouldUseSnakeCase()
    {
        // Arrange
        var request = new HoneyBox.Model.Models.Lottery.PrizeOrderLogRequest
        {
            OrderNum = "TEST001"
        };

        // Act
        var json = JsonSerializer.Serialize(request, _jsonOptions);

        // Assert
        Assert.Contains("\"order_num\":", json);
        Assert.DoesNotContain("\"OrderNum\":", json);
    }

    /// <summary>
    /// 验证InfiniteShangLogRequest使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void InfiniteShangLogRequest_ShouldUseSnakeCase()
    {
        // Arrange
        var request = new InfiniteShangLogRequest
        {
            GoodsId = 1,
            ShangId = 10,
            IsMibao = 0,
            Page = 1,
            PageSize = 10
        };

        // Act
        var json = JsonSerializer.Serialize(request, _jsonOptions);

        // Assert
        Assert.Contains("\"goods_id\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"is_mibao\":", json);
        Assert.Contains("\"page\":", json);
        Assert.Contains("\"page_size\":", json);
    }

    /// <summary>
    /// 验证DailyPrizeRecordsRequest使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void DailyPrizeRecordsRequest_ShouldUseSnakeCase()
    {
        // Arrange
        var request = new DailyPrizeRecordsRequest
        {
            GoodsId = 1,
            Page = 1,
            PageSize = 10
        };

        // Act
        var json = JsonSerializer.Serialize(request, _jsonOptions);

        // Assert
        Assert.Contains("\"goods_id\":", json);
        Assert.Contains("\"page\":", json);
        Assert.Contains("\"page_size\":", json);
    }

    /// <summary>
    /// 验证ItemCardDrawRequest使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void ItemCardDrawRequest_ShouldUseSnakeCase()
    {
        // Arrange
        var request = new ItemCardDrawRequest
        {
            GoodsId = 1,
            OrderListIds = "1,2,3"
        };

        // Act
        var json = JsonSerializer.Serialize(request, _jsonOptions);

        // Assert
        Assert.Contains("\"goods_id\":", json);
        Assert.Contains("\"order_list_ids\":", json);
    }

    /// <summary>
    /// 验证InfiniteShangLogResponseDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void InfiniteShangLogResponseDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new InfiniteShangLogResponseDto
        {
            Category = new List<ShangCategoryDto>
            {
                new() { ShangId = 0, ShangTitle = "全部" },
                new() { ShangId = 10, ShangTitle = "A赏" }
            },
            Data = new List<InfiniteShangLogItemDto>(),
            LastPage = 1,
            Total = 10
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"category\":", json);
        Assert.Contains("\"data\":", json);
        Assert.Contains("\"last_page\":", json);
        Assert.Contains("\"total\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"shang_title\":", json);
    }

    /// <summary>
    /// 验证InfiniteShangLogItemDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void InfiniteShangLogItemDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new InfiniteShangLogItemDto
        {
            Id = 1,
            UserId = 1,
            GoodslistTitle = "测试奖品",
            GoodslistImgurl = "http://test.com/img.jpg",
            GoodslistPrice = "100.00",
            GoodslistMoney = "50.00",
            ShangId = 10,
            ShangTitle = "A赏",
            ShangColor = "#FF0000",
            PrizeNum = 1,
            Addtime = "2024-01-01 12:00:00",
            LuckNo = 1,
            Doubling = 1,
            IsLingzhu = 0,
            UserInfo = new LotteryUserInfoDto
            {
                Nickname = "测***户",
                HeadImg = "avatar.jpg"
            }
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"user_id\":", json);
        Assert.Contains("\"goodslist_title\":", json);
        Assert.Contains("\"goodslist_imgurl\":", json);
        Assert.Contains("\"goodslist_price\":", json);
        Assert.Contains("\"goodslist_money\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"shang_title\":", json);
        Assert.Contains("\"shang_color\":", json);
        Assert.Contains("\"prize_num\":", json);
        Assert.Contains("\"addtime\":", json);
        Assert.Contains("\"luck_no\":", json);
        Assert.Contains("\"doubling\":", json);
        Assert.Contains("\"is_lingzhu\":", json);
        Assert.Contains("\"user_info\":", json);
        Assert.Contains("\"nickname\":", json);
        Assert.Contains("\"headimg\":", json);
    }

    /// <summary>
    /// 验证DailyPrizeRecordItemDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void DailyPrizeRecordItemDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new DailyPrizeRecordItemDto
        {
            Id = 1,
            UserId = 1,
            GoodslistTitle = "测试奖品",
            GoodslistImgurl = "http://test.com/img.jpg",
            ShangId = 10,
            ShangTitle = "A赏",
            Addtime = "2024-01-01 12:00:00"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"user_id\":", json);
        Assert.Contains("\"goodslist_title\":", json);
        Assert.Contains("\"goodslist_imgurl\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"shang_title\":", json);
        Assert.Contains("\"addtime\":", json);
    }

    /// <summary>
    /// 验证InfinitePrizeRecordsResponseDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void InfinitePrizeRecordsResponseDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new InfinitePrizeRecordsResponseDto
        {
            Data = new List<InfinitePrizeRecordItemDto>(),
            CurrentPage = 1,
            LastPage = 10,
            PerPage = 10,
            Total = 100
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"data\":", json);
        Assert.Contains("\"current_page\":", json);
        Assert.Contains("\"last_page\":", json);
        Assert.Contains("\"per_page\":", json);
        Assert.Contains("\"total\":", json);
    }

    /// <summary>
    /// 验证InfinitePrizeRecordItemDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void InfinitePrizeRecordItemDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new InfinitePrizeRecordItemDto
        {
            UserId = 1,
            GoodslistTitle = "测试奖品",
            GoodslistImgurl = "http://test.com/img.jpg",
            Addtime = "2024-01-01 12:00:00"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"user_id\":", json);
        Assert.Contains("\"goodslist_title\":", json);
        Assert.Contains("\"goodslist_imgurl\":", json);
        Assert.Contains("\"addtime\":", json);
    }

    /// <summary>
    /// 验证ItemCardDrawResponseDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void ItemCardDrawResponseDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new ItemCardDrawResponseDto
        {
            Status = 0,
            OrderNum = "TEST001",
            Prizes = new List<ItemCardDrawPrizeDto>
            {
                new()
                {
                    Id = 1,
                    Title = "测试奖品",
                    ImgUrl = "http://test.com/img.jpg",
                    ShangId = 10,
                    ShangTitle = "A赏",
                    ShangColor = "#FF0000",
                    Price = "100.00",
                    ScMoney = "50.00",
                    PrizeCode = "PRIZE001",
                    LuckNo = 1
                }
            },
            RemainingCards = 5
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"order_num\":", json);
        Assert.Contains("\"prizes\":", json);
        Assert.Contains("\"remaining_cards\":", json);
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"title\":", json);
        Assert.Contains("\"img_url\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"shang_title\":", json);
        Assert.Contains("\"shang_color\":", json);
        Assert.Contains("\"price\":", json);
        Assert.Contains("\"sc_money\":", json);
        Assert.Contains("\"prize_code\":", json);
        Assert.Contains("\"luck_no\":", json);
    }

    /// <summary>
    /// 验证PrizeOrderLogResponseDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void PrizeOrderLogResponseDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new PrizeOrderLogResponseDto
        {
            Data = new List<PrizeOrderLogDto>
            {
                new()
                {
                    Id = 1,
                    UserId = 1,
                    GoodsListTitle = "测试奖品",
                    GoodsListImgUrl = "http://test.com/img.jpg",
                    GoodsListPrice = "100.00",
                    GoodsListMoney = "50.00",
                    Status = 0,
                    LuckNo = 1,
                    ShangId = 10,
                    ShangTitle = "A赏",
                    Doubling = 1,
                    IsLingzhu = 0,
                    GoodsListType = 1,
                    GoodsListId = 1,
                    ParentGoodsListId = 0,
                    PrizeNum = 1,
                    AddTime = 1234567890
                }
            },
            ItemCardCount = 5,
            PrizeNum = 1
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"data\":", json);
        Assert.Contains("\"item_card_count\":", json);
        Assert.Contains("\"prize_num\":", json);
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"user_id\":", json);
        Assert.Contains("\"goodslist_title\":", json);
        Assert.Contains("\"goodslist_imgurl\":", json);
        Assert.Contains("\"goodslist_price\":", json);
        Assert.Contains("\"goodslist_money\":", json);
        Assert.Contains("\"status\":", json);
        Assert.Contains("\"luck_no\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"shang_title\":", json);
        Assert.Contains("\"doubling\":", json);
        Assert.Contains("\"is_lingzhu\":", json);
        Assert.Contains("\"goodslist_type\":", json);
        Assert.Contains("\"goodslist_id\":", json);
        Assert.Contains("\"parent_goods_list_id\":", json);
        Assert.Contains("\"addtime\":", json);
    }

    /// <summary>
    /// 验证InfinitePrizeOrderLogResponseDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void InfinitePrizeOrderLogResponseDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new InfinitePrizeOrderLogResponseDto
        {
            UserInfo = new UserBasicInfoDto
            {
                Nickname = "测试用户",
                HeadImg = "avatar.jpg"
            },
            Data = new List<PrizeOrderLogDto>(),
            ItemCardCount = 5,
            PrizeNum = 1
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"user_info\":", json);
        Assert.Contains("\"data\":", json);
        Assert.Contains("\"item_card_count\":", json);
        Assert.Contains("\"prize_num\":", json);
        Assert.Contains("\"nickname\":", json);
        Assert.Contains("\"headimg\":", json);
    }

    /// <summary>
    /// 验证完整的无限赏中奖记录响应格式与PHP API一致
    /// Requirements: 10.1-10.4
    /// </summary>
    [Fact]
    public void CompleteInfiniteShangLogResponse_ShouldMatchPhpFormat()
    {
        // Arrange - 模拟PHP API返回的格式
        var data = new InfiniteShangLogResponseDto
        {
            Category = new List<ShangCategoryDto>
            {
                new() { ShangId = 0, ShangTitle = "全部" },
                new() { ShangId = 10, ShangTitle = "A赏" }
            },
            Data = new List<InfiniteShangLogItemDto>
            {
                new()
                {
                    Id = 1,
                    UserId = 1,
                    GoodslistTitle = "测试奖品",
                    GoodslistImgurl = "http://test.com/img.jpg",
                    GoodslistPrice = "100.00",
                    GoodslistMoney = "50.00",
                    ShangId = 10,
                    ShangTitle = "A赏",
                    ShangColor = "#FF0000",
                    PrizeNum = 1,
                    Addtime = "2024-01-01 12:00:00",
                    LuckNo = 1,
                    Doubling = 1,
                    IsLingzhu = 0,
                    UserInfo = new LotteryUserInfoDto
                    {
                        Nickname = "测***户",
                        HeadImg = "avatar.jpg"
                    }
                }
            },
            LastPage = 1,
            Total = 1
        };
        var response = ApiResponse<InfiniteShangLogResponseDto>.Success(data);

        // Act
        var json = JsonSerializer.Serialize(response, _jsonOptions);

        // Assert - 验证顶层结构
        Assert.Contains("\"status\":1", json);
        Assert.Contains("\"msg\":\"success\"", json);
        Assert.Contains("\"data\":", json);

        // Assert - 验证数据字段使用snake_case
        Assert.Contains("\"category\":", json);
        Assert.Contains("\"last_page\":", json);
        Assert.Contains("\"total\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"shang_title\":", json);
        Assert.Contains("\"user_id\":", json);
        Assert.Contains("\"goodslist_title\":", json);
        Assert.Contains("\"goodslist_imgurl\":", json);
        Assert.Contains("\"goodslist_price\":", json);
        Assert.Contains("\"goodslist_money\":", json);
        Assert.Contains("\"shang_color\":", json);
        Assert.Contains("\"prize_num\":", json);
        Assert.Contains("\"addtime\":", json);
        Assert.Contains("\"luck_no\":", json);
        Assert.Contains("\"doubling\":", json);
        Assert.Contains("\"is_lingzhu\":", json);
        Assert.Contains("\"user_info\":", json);
        Assert.Contains("\"nickname\":", json);
        Assert.Contains("\"headimg\":", json);
    }

    /// <summary>
    /// 验证完整的道具卡抽奖响应格式与PHP API一致
    /// Requirements: 10.1-10.4
    /// </summary>
    [Fact]
    public void CompleteItemCardDrawResponse_ShouldMatchPhpFormat()
    {
        // Arrange
        var data = new ItemCardDrawResponseDto
        {
            Status = 0,
            OrderNum = "MH_20240101120000001",
            Prizes = new List<ItemCardDrawPrizeDto>
            {
                new()
                {
                    Id = 1,
                    Title = "A赏奖品",
                    ImgUrl = "http://test.com/prize.jpg",
                    ShangId = 10,
                    ShangTitle = "A赏",
                    ShangColor = "#FF0000",
                    Price = "100.00",
                    ScMoney = "50.00",
                    PrizeCode = "PRIZE20240101001",
                    LuckNo = 88
                }
            },
            RemainingCards = 4
        };
        var response = ApiResponse<ItemCardDrawResponseDto>.Success(data, "重抽成功");

        // Act
        var json = JsonSerializer.Serialize(response, _jsonOptions);

        // Assert - 验证顶层结构
        Assert.Contains("\"status\":1", json);
        Assert.Contains("\"data\":", json);

        // Assert - 验证数据字段使用snake_case
        Assert.Contains("\"order_num\":", json);
        Assert.Contains("\"prizes\":", json);
        Assert.Contains("\"remaining_cards\":", json);
        Assert.Contains("\"img_url\":", json);
        Assert.Contains("\"shang_id\":", json);
        Assert.Contains("\"shang_title\":", json);
        Assert.Contains("\"shang_color\":", json);
        Assert.Contains("\"sc_money\":", json);
        Assert.Contains("\"prize_code\":", json);
        Assert.Contains("\"luck_no\":", json);
    }

    /// <summary>
    /// 验证抽奖系统失败响应格式
    /// Requirements: 10.1, 10.3
    /// </summary>
    [Fact]
    public void LotteryFailResponse_ShouldMatchPhpFormat()
    {
        // Arrange - 模拟PHP API返回的失败格式
        var response = ApiResponse<InfiniteShangLogResponseDto>.Fail("盒子不存在");

        // Act
        var json = JsonSerializer.Serialize(response, _jsonOptions);

        // Assert
        Assert.Contains("\"status\":0", json);
        Assert.Contains("\"msg\":", json);
        
        // 验证反序列化后内容正确
        var deserialized = JsonSerializer.Deserialize<ApiResponse<InfiniteShangLogResponseDto>>(json, _jsonOptions);
        Assert.NotNull(deserialized);
        Assert.Equal(0, deserialized.Status);
        Assert.Equal("盒子不存在", deserialized.Msg);
    }

    /// <summary>
    /// 验证ShangInfoDto使用snake_case（用于赏品等级信息）
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void ShangInfoDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new ShangInfoDto
        {
            Id = 10,
            Title = "A赏",
            ImgUrl = "http://test.com/shang.jpg",
            Color = "#FF0000",
            SpecialImgUrl = "http://test.com/special.jpg"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"id\":", json);
        Assert.Contains("\"title\":", json);
        Assert.Contains("\"img_url\":", json);
        Assert.Contains("\"color\":", json);
        Assert.Contains("\"special_img_url\":", json);
    }

    /// <summary>
    /// 验证LotteryUserInfoDto使用snake_case
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public void LotteryUserInfoDto_ShouldUseSnakeCase()
    {
        // Arrange
        var dto = new LotteryUserInfoDto
        {
            Nickname = "测***户",
            HeadImg = "avatar.jpg"
        };

        // Act
        var json = JsonSerializer.Serialize(dto, _jsonOptions);

        // Assert
        Assert.Contains("\"nickname\":", json);
        Assert.Contains("\"headimg\":", json);
    }

    #endregion
}
