using HoneyBox.Core.Interfaces;
using HoneyBox.Core.Services;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models.Order;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;

namespace HoneyBox.Tests.Integration;

/// <summary>
/// 仓库服务集成测试
/// 测试奖品回收和发货流程
/// Requirements: 10.1-17.3
/// </summary>
public class WarehouseServiceIntegrationTests
{
    private HoneyBoxDbContext CreateInMemoryDbContext()
    {
        var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
            .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
            .ConfigureWarnings(w => w.Ignore(InMemoryEventId.TransactionIgnoredWarning))
            .Options;

        return new HoneyBoxDbContext(options);
    }

    private WarehouseService CreateWarehouseService(HoneyBoxDbContext dbContext)
    {
        var mockLogger = new Mock<ILogger<WarehouseService>>();
        var mockLogisticsService = new Mock<ILogisticsService>();
        var mockWechatPayService = new Mock<IWechatPayService>();
        return new WarehouseService(dbContext, mockLogger.Object, mockLogisticsService.Object, mockWechatPayService.Object);
    }

    #region 测试数据准备

    private async Task<User> CreateTestUserAsync(HoneyBoxDbContext dbContext, decimal money2 = 0)
    {
        var user = new User
        {
            Id = 1,
            OpenId = "test_openid",
            Uid = "test_uid",
            Nickname = "测试用户",
            HeadImg = "avatar.jpg",
            Mobile = "13800138000",
            Money = 100,
            Integral = 1000,
            Money2 = money2,
            Status = 1,
            CreatedAt = DateTime.Now,
            UpdatedAt = DateTime.Now
        };
        await dbContext.Users.AddAsync(user);
        await dbContext.SaveChangesAsync();
        return user;
    }

    private async Task<Good> CreateTestGoodsAsync(HoneyBoxDbContext dbContext)
    {
        var goods = new Good
        {
            Id = 1,
            Title = "测试商品",
            Type = 1,
            Status = 1,
            Price = 10,
            Stock = 10,
            ImgUrl = "img.jpg",
            ImgUrlDetail = "detail.jpg"
        };
        await dbContext.Goods.AddAsync(goods);
        await dbContext.SaveChangesAsync();
        return goods;
    }

    private async Task<List<OrderItem>> CreateTestOrderItemsAsync(HoneyBoxDbContext dbContext, int userId, int count = 3)
    {
        var items = new List<OrderItem>();
        for (int i = 1; i <= count; i++)
        {
            items.Add(new OrderItem
            {
                Id = i,
                OrderId = 1,
                UserId = userId,
                GoodsId = 1,
                ShangId = 10,
                GoodslistId = i,
                GoodslistTitle = $"奖品{i}",
                GoodslistImgurl = $"prize{i}.jpg",
                GoodslistPrice = 100,
                GoodslistMoney = 50, // 回收金额50
                GoodslistType = 1, // 现货
                Status = 0, // 待处理
                InsuranceIs = 0,
                OrderType = 1,
                PrizeCode = $"PRIZE_{i}",
                Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                CreatedAt = DateTime.Now,
                UpdatedAt = DateTime.Now
            });
        }
        await dbContext.OrderItems.AddRangeAsync(items);
        await dbContext.SaveChangesAsync();
        return items;
    }

    #endregion

    #region 仓库首页查询测试 (Requirements 10.1-10.3)

    /// <summary>
    /// 测试仓库首页查询 - 赏品类型
    /// Requirements: 10.1, 10.2
    /// </summary>
    [Fact]
    public async Task GetWarehouseIndex_PrizesType_ReturnsCorrectItems()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);
        await CreateTestGoodsAsync(dbContext);
        await CreateTestOrderItemsAsync(dbContext, 1, 5);

        var request = new WarehouseIndexRequest
        {
            Type = 1, // 赏品
            Page = 1
        };

        // Act
        var result = await service.GetWarehouseIndexAsync(1, request);

        // Assert
        Assert.NotNull(result);
        Assert.True(result.Total > 0);
        Assert.NotEmpty(result.Data);
    }

    /// <summary>
    /// 测试仓库首页查询 - 状态筛选
    /// Requirements: 10.2
    /// </summary>
    [Fact]
    public async Task GetWarehouseIndex_FiltersByStatus_ReturnsFilteredItems()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);
        await CreateTestGoodsAsync(dbContext);

        // 创建不同状态的奖品
        var items = new List<OrderItem>
        {
            new() { Id = 1, OrderId = 1, UserId = 1, GoodsId = 1, ShangId = 10, GoodslistTitle = "待处理奖品", GoodslistMoney = 50, GoodslistType = 1, Status = 0, InsuranceIs = 0, OrderType = 1, PrizeCode = "P1", Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
            new() { Id = 2, OrderId = 1, UserId = 1, GoodsId = 1, ShangId = 10, GoodslistTitle = "已回收奖品", GoodslistMoney = 50, GoodslistType = 1, Status = 1, InsuranceIs = 0, OrderType = 1, PrizeCode = "P2", Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
            new() { Id = 3, OrderId = 1, UserId = 1, GoodsId = 1, ShangId = 10, GoodslistTitle = "已发货奖品", GoodslistMoney = 50, GoodslistType = 1, Status = 2, InsuranceIs = 0, OrderType = 1, PrizeCode = "P3", Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
        };
        await dbContext.OrderItems.AddRangeAsync(items);
        await dbContext.SaveChangesAsync();

        var request = new WarehouseIndexRequest
        {
            Type = 1,
            Page = 1
        };

        // Act
        var result = await service.GetWarehouseIndexAsync(1, request);

        // Assert
        Assert.NotNull(result);
        // 只返回status=0的待处理奖品
        Assert.Equal(1, result.Total);
    }

    /// <summary>
    /// 测试仓库首页查询 - 无限赏类型
    /// Requirements: 10.3
    /// </summary>
    [Fact]
    public async Task GetWarehouseIndex_InfiniteType_ReturnsInfiniteItems()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);
        await CreateTestGoodsAsync(dbContext);

        // 创建无限赏奖品
        var items = new List<OrderItem>
        {
            new() { Id = 1, OrderId = 1, UserId = 1, GoodsId = 1, ShangId = 34, GoodslistTitle = "无限赏奖品", GoodslistMoney = 50, GoodslistType = 1, Status = 0, InsuranceIs = 0, OrderType = 2, PrizeCode = "INF1", Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
        };
        await dbContext.OrderItems.AddRangeAsync(items);
        await dbContext.SaveChangesAsync();

        var request = new WarehouseIndexRequest
        {
            Type = 5, // 无限赏
            Page = 1
        };

        // Act
        var result = await service.GetWarehouseIndexAsync(1, request);

        // Assert
        Assert.NotNull(result);
        Assert.Equal(1, result.Total);
    }

    #endregion

    #region 奖品回收测试 (Requirements 11.1-11.5)

    /// <summary>
    /// 测试奖品回收 - 成功回收
    /// Requirements: 11.1, 11.2, 11.3, 11.4
    /// Note: This test requires a real database due to transaction and ExecuteUpdate usage
    /// </summary>
    [Fact(Skip = "InMemory database does not support transactions and ExecuteUpdate")]
    public async Task RecoveryPrizes_Success_UpdatesStatusAndBalance()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext, money2: 0);
        await CreateTestGoodsAsync(dbContext);
        await CreateTestOrderItemsAsync(dbContext, 1, 2);

        // 构建回收信息
        var recoveryInfo = System.Text.Json.JsonSerializer.Serialize(new[]
        {
            new { prize_code = "PRIZE_1", number = 1 },
            new { prize_code = "PRIZE_2", number = 1 }
        });

        var request = new RecoveryRequest
        {
            RecoveryInfo = recoveryInfo
        };

        // Act
        var result = await service.RecoveryPrizesAsync(1, request);

        // Assert
        Assert.NotNull(result);
        Assert.Equal(2, result.Count);
        Assert.NotEmpty(result.RecoveryNum);

        // 验证奖品状态已更新
        var items = await dbContext.OrderItems.Where(o => o.UserId == 1).ToListAsync();
        Assert.All(items, item => Assert.Equal(1, item.Status)); // 已回收

        // 验证用户余额已增加 (50 * 2 * 100 = 10000 哈尼券)
        var user = await dbContext.Users.FindAsync(1);
        Assert.NotNull(user);
        Assert.Equal(10000, user.Money2);
    }

    /// <summary>
    /// 测试奖品回收 - 空回收信息
    /// Requirements: 11.5
    /// </summary>
    [Fact]
    public async Task RecoveryPrizes_EmptyInfo_ThrowsException()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);

        var request = new RecoveryRequest
        {
            RecoveryInfo = ""
        };

        // Act & Assert
        var ex = await Assert.ThrowsAsync<InvalidOperationException>(
            () => service.RecoveryPrizesAsync(1, request));
        Assert.Contains("选择", ex.Message);
    }

    /// <summary>
    /// 测试奖品回收 - 无效的回收信息格式
    /// Requirements: 11.5
    /// </summary>
    [Fact]
    public async Task RecoveryPrizes_InvalidFormat_ThrowsException()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);

        var request = new RecoveryRequest
        {
            RecoveryInfo = "invalid json"
        };

        // Act & Assert
        var ex = await Assert.ThrowsAsync<InvalidOperationException>(
            () => service.RecoveryPrizesAsync(1, request));
        Assert.Contains("格式错误", ex.Message);
    }

    #endregion

    #region 奖品发货测试 (Requirements 12.1-12.5, 13.1-13.2)

    /// <summary>
    /// 测试奖品发货申请 - 成功
    /// Requirements: 12.1, 12.2, 12.3, 12.4
    /// Note: This test requires a real database due to transaction usage
    /// </summary>
    [Fact(Skip = "InMemory database does not support transactions")]
    public async Task SendPrizes_Success_CreatesDeliveryRecord()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);
        await CreateTestGoodsAsync(dbContext);
        await CreateTestOrderItemsAsync(dbContext, 1, 2);

        // 构建发货信息JSON
        var recoveryInfo = System.Text.Json.JsonSerializer.Serialize(new[]
        {
            new { prize_code = "PRIZE_1", number = 1 },
            new { prize_code = "PRIZE_2", number = 1 }
        });

        var request = new SendRequest
        {
            Type = 1,
            RecoveryInfo = recoveryInfo,
            Name = "张三",
            Mobile = "13800138000",
            Address = "北京市朝阳区xxx街道xxx号"
        };

        // Act
        var result = await service.SendPrizesAsync(1, request);

        // Assert
        Assert.NotNull(result);
        Assert.NotEmpty(result.OrderNo);

        // 验证发货记录已创建
        var delivery = await dbContext.OrderItemsSends.FirstOrDefaultAsync();
        Assert.NotNull(delivery);
        Assert.Equal("张三", delivery.Name);
    }

    /// <summary>
    /// 测试奖品发货申请 - 地址信息不完整
    /// Requirements: 12.5
    /// </summary>
    [Fact]
    public async Task SendPrizes_IncompleteAddress_ThrowsException()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);
        await CreateTestGoodsAsync(dbContext);
        await CreateTestOrderItemsAsync(dbContext, 1);

        var recoveryInfo = System.Text.Json.JsonSerializer.Serialize(new[]
        {
            new { prize_code = "PRIZE_1", number = 1 }
        });

        var request = new SendRequest
        {
            Type = 1,
            RecoveryInfo = recoveryInfo,
            Name = "", // 空姓名
            Mobile = "13800138000",
            Address = "北京市"
        };

        // Act & Assert
        var ex = await Assert.ThrowsAsync<InvalidOperationException>(
            () => service.SendPrizesAsync(1, request));
        Assert.Contains("收货", ex.Message);
    }

    /// <summary>
    /// 测试奖品发货申请 - 空订单列表
    /// Requirements: 12.5
    /// </summary>
    [Fact]
    public async Task SendPrizes_EmptyOrderList_ThrowsException()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);

        var request = new SendRequest
        {
            Type = 1,
            RecoveryInfo = "",
            Name = "张三",
            Mobile = "13800138000",
            Address = "北京市"
        };

        // Act & Assert
        var ex = await Assert.ThrowsAsync<InvalidOperationException>(
            () => service.SendPrizesAsync(1, request));
        Assert.Contains("选择", ex.Message);
    }

    #endregion

    #region 发货记录查询测试 (Requirements 14.1-14.3, 15.1-15.3)

    /// <summary>
    /// 测试发货记录查询 - 分页
    /// Requirements: 14.1, 14.3
    /// Note: This test requires a real database due to ExecuteUpdate usage in the service
    /// </summary>
    [Fact(Skip = "InMemory database does not support ExecuteUpdate")]
    public async Task GetSendRecords_Pagination_ReturnsCorrectPage()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);

        // 创建15条发货记录
        var records = Enumerable.Range(1, 15).Select(i => new OrderItemsSend
        {
            Id = i,
            UserId = 1,
            SendNum = $"SEND_{i:0000}",
            Name = $"收货人{i}",
            Mobile = "138****8000",
            Address = $"地址{i}",
            Status = 1, // 待发货
            Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds() - i * 60,
            CreatedAt = DateTime.Now,
            UpdatedAt = DateTime.Now
        }).ToList();
        await dbContext.OrderItemsSends.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act
        var page1 = await service.GetSendRecordsAsync(1, 1, 1);
        var page2 = await service.GetSendRecordsAsync(1, 2, 1);

        // Assert
        Assert.Equal(15, page1.Total);
        Assert.Equal(10, page1.Data.Count);
        Assert.Equal(5, page2.Data.Count);
    }

    /// <summary>
    /// 测试发货记录详情查询
    /// Requirements: 15.1, 15.2
    /// </summary>
    [Fact]
    public async Task GetSendRecordDetail_ReturnsCompleteInfo()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);

        // 创建发货记录
        var sendRecord = new OrderItemsSend
        {
            Id = 1,
            UserId = 1,
            SendNum = "SEND_0001",
            Name = "张三",
            Mobile = "13800138000",
            Address = "北京市朝阳区",
            Status = 1, // 待发货
            Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
            CreatedAt = DateTime.Now,
            UpdatedAt = DateTime.Now
        };
        await dbContext.OrderItemsSends.AddAsync(sendRecord);

        // 创建关联的奖品
        var items = new List<OrderItem>
        {
            new() { Id = 1, OrderId = 1, UserId = 1, GoodsId = 1, ShangId = 10, SendNum = "SEND_0001", GoodslistTitle = "奖品1", GoodslistMoney = 50, Status = 2, Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
        };
        await dbContext.OrderItems.AddRangeAsync(items);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetSendRecordDetailAsync(1, 1);

        // Assert
        Assert.NotNull(result);
        Assert.Equal("SEND_0001", result.SendNum);
        Assert.Equal("张三", result.Name);
        Assert.NotNull(result.Goods);
    }

    /// <summary>
    /// 测试发货记录详情查询 - 记录不存在
    /// Requirements: 15.3
    /// </summary>
    [Fact]
    public async Task GetSendRecordDetail_NotFound_ThrowsException()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);

        // Act & Assert
        var ex = await Assert.ThrowsAsync<InvalidOperationException>(
            () => service.GetSendRecordDetailAsync(1, 999));
        Assert.Contains("参数错误", ex.Message);
    }

    #endregion

    #region 回收记录查询测试 (Requirements 16.1-16.2)

    /// <summary>
    /// 测试回收记录查询 - 分页
    /// Requirements: 16.1, 16.2
    /// </summary>
    [Fact]
    public async Task GetRecoveryRecords_Pagination_ReturnsCorrectPage()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateWarehouseService(dbContext);

        await CreateTestUserAsync(dbContext);

        // 创建10条回收记录
        var records = Enumerable.Range(1, 10).Select(i => new OrderItemsRecovery
        {
            Id = i,
            UserId = 1,
            RecoveryNum = $"REC_{i:0000}",
            Money = 50 * i,
            Count = i,
            Addtime = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds() - i * 60,
            CreatedAt = DateTime.Now,
            UpdatedAt = DateTime.Now
        }).ToList();
        await dbContext.OrderItemsRecoveries.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetRecoveryRecordsAsync(1, 1);

        // Assert
        Assert.NotNull(result);
        Assert.NotNull(result.Data);
        Assert.True(result.Data.Count <= 10);
        Assert.True(result.LastPage >= 1);
    }

    #endregion
}
