using HoneyBox.Core.Services;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;

namespace HoneyBox.Tests.Integration;

/// <summary>
/// 资产服务集成测试
/// 测试完整的资产查询流程
/// Requirements: 1.1-1.6
/// </summary>
public class AssetServiceIntegrationTests
{
    private HoneyBoxDbContext CreateInMemoryDbContext()
    {
        var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
            .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
            .Options;

        return new HoneyBoxDbContext(options);
    }

    private AssetService CreateAssetService(HoneyBoxDbContext dbContext)
    {
        var mockLogger = new Mock<ILogger<AssetService>>();
        return new AssetService(dbContext, mockLogger.Object);
    }

    /// <summary>
    /// 测试余额明细查询 - 全部记录
    /// Requirements: 1.1
    /// </summary>
    [Fact]
    public async Task GetMoneyRecords_AllTypes_ReturnsAllRecords()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        // 添加测试数据
        var records = new List<ProfitMoney>
        {
            new() { UserId = userId, ChangeMoney = 100, Money = 100, Type = 1, Content = "充值", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -50, Money = 50, Type = 2, Content = "消费", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -30, Money = 20, Type = 4, Content = "提现", CreatedAt = DateTime.Now }
        };
        await dbContext.ProfitMoneys.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetMoneyRecordsAsync(userId, 0, 1, 15);

        // Assert
        Assert.NotNull(result);
        Assert.Equal(3, result.Total);
        Assert.Equal(3, result.List.Count);
        Assert.Equal(1, result.LastPage);
    }

    /// <summary>
    /// 测试余额明细查询 - 收入过滤
    /// Requirements: 1.1
    /// </summary>
    [Fact]
    public async Task GetMoneyRecords_IncomeFilter_ReturnsOnlyIncome()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        var records = new List<ProfitMoney>
        {
            new() { UserId = userId, ChangeMoney = 100, Money = 100, Type = 1, Content = "充值", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = 50, Money = 150, Type = 2, Content = "奖励", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -30, Money = 120, Type = 3, Content = "消费", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -20, Money = 100, Type = 4, Content = "提现", CreatedAt = DateTime.Now }
        };
        await dbContext.ProfitMoneys.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act - type=1 表示收入 (change_money > 0, type != 4)
        var result = await service.GetMoneyRecordsAsync(userId, 1, 1, 15);

        // Assert
        Assert.Equal(2, result.Total);
        Assert.All(result.List, r => Assert.True(decimal.Parse(r.ChangeMoney) > 0));
    }

    /// <summary>
    /// 测试余额明细查询 - 支出过滤
    /// Requirements: 1.1
    /// </summary>
    [Fact]
    public async Task GetMoneyRecords_ExpenseFilter_ReturnsOnlyExpense()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        var records = new List<ProfitMoney>
        {
            new() { UserId = userId, ChangeMoney = 100, Money = 100, Type = 1, Content = "充值", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -30, Money = 70, Type = 3, Content = "消费", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -20, Money = 50, Type = 4, Content = "提现", CreatedAt = DateTime.Now }
        };
        await dbContext.ProfitMoneys.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act - type=2 表示支出 (change_money < 0, type != 4)
        var result = await service.GetMoneyRecordsAsync(userId, 2, 1, 15);

        // Assert
        Assert.Equal(1, result.Total);
        Assert.All(result.List, r => Assert.True(decimal.Parse(r.ChangeMoney) < 0));
    }

    /// <summary>
    /// 测试余额明细查询 - 提现过滤
    /// Requirements: 1.1
    /// </summary>
    [Fact]
    public async Task GetMoneyRecords_WithdrawFilter_ReturnsOnlyWithdraw()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        var records = new List<ProfitMoney>
        {
            new() { UserId = userId, ChangeMoney = 100, Money = 100, Type = 1, Content = "充值", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -30, Money = 70, Type = 4, Content = "提现1", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -20, Money = 50, Type = 4, Content = "提现2", CreatedAt = DateTime.Now }
        };
        await dbContext.ProfitMoneys.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act - type=3 表示提现 (type = 4)
        var result = await service.GetMoneyRecordsAsync(userId, 3, 1, 15);

        // Assert
        Assert.Equal(2, result.Total);
    }

    /// <summary>
    /// 测试吧唧币明细查询
    /// Requirements: 1.2
    /// </summary>
    [Fact]
    public async Task GetIntegralRecords_ReturnsCorrectRecords()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        var records = new List<ProfitIntegral>
        {
            new() { UserId = userId, ChangeMoney = 100, Money = 100, Type = 1, Content = "签到奖励", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -50, Money = 50, Type = 2, Content = "兑换消费", CreatedAt = DateTime.Now }
        };
        await dbContext.ProfitIntegrals.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetIntegralRecordsAsync(userId, 0, 1, 15);

        // Assert
        Assert.Equal(2, result.Total);
        Assert.Equal(2, result.List.Count);
    }

    /// <summary>
    /// 测试积分明细查询
    /// Requirements: 1.3
    /// </summary>
    [Fact]
    public async Task GetScoreRecords_ReturnsCorrectRecords()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        var records = new List<ProfitMoney2>
        {
            new() { UserId = userId, ChangeMoney = 200, Money = 200, Type = 1, Content = "任务奖励", CreatedAt = DateTime.Now },
            new() { UserId = userId, ChangeMoney = -100, Money = 100, Type = 2, Content = "积分消费", CreatedAt = DateTime.Now }
        };
        await dbContext.ProfitMoney2s.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetScoreRecordsAsync(userId, 0, 1, 15);

        // Assert
        Assert.Equal(2, result.Total);
        Assert.Equal(2, result.List.Count);
    }

    /// <summary>
    /// 测试支付记录查询
    /// Requirements: 1.4
    /// </summary>
    [Fact]
    public async Task GetPayRecords_ReturnsCorrectRecords()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        var records = new List<ProfitPay>
        {
            new() { UserId = userId, OrderNum = "ORD001", ChangeMoney = 99.9m, Content = "购买商品", PayType = 0, CreatedAt = DateTime.Now },
            new() { UserId = userId, OrderNum = "ORD002", ChangeMoney = 199.9m, Content = "购买商品", PayType = 1, CreatedAt = DateTime.Now }
        };
        await dbContext.ProfitPays.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetPayRecordsAsync(userId, 1, 15);

        // Assert
        Assert.Equal(2, result.Total);
        Assert.Equal(2, result.List.Count);
    }

    /// <summary>
    /// 测试时间格式化
    /// Requirements: 1.5
    /// </summary>
    [Fact]
    public async Task GetMoneyRecords_FormatsTimestampCorrectly()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;
        var testTime = new DateTime(2025, 6, 15, 14, 30, 45);

        var record = new ProfitMoney
        {
            UserId = userId,
            ChangeMoney = 100,
            Money = 100,
            Type = 1,
            Content = "测试",
            CreatedAt = testTime
        };
        await dbContext.ProfitMoneys.AddAsync(record);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetMoneyRecordsAsync(userId, 0, 1, 15);

        // Assert
        Assert.Single(result.List);
        Assert.Equal("2025-06-15 14:30:45", result.List[0].AddTime);
    }

    /// <summary>
    /// 测试分页功能
    /// Requirements: 1.6
    /// </summary>
    [Fact]
    public async Task GetMoneyRecords_PaginationWorksCorrectly()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        // 添加25条记录
        var records = Enumerable.Range(1, 25).Select(i => new ProfitMoney
        {
            UserId = userId,
            ChangeMoney = i * 10,
            Money = i * 10,
            Type = 1,
            Content = $"记录{i}",
            CreatedAt = DateTime.Now.AddMinutes(-i)
        }).ToList();
        await dbContext.ProfitMoneys.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act - 第一页
        var page1 = await service.GetMoneyRecordsAsync(userId, 0, 1, 10);
        // Act - 第二页
        var page2 = await service.GetMoneyRecordsAsync(userId, 0, 2, 10);
        // Act - 第三页
        var page3 = await service.GetMoneyRecordsAsync(userId, 0, 3, 10);

        // Assert
        Assert.Equal(25, page1.Total);
        Assert.Equal(3, page1.LastPage);
        Assert.Equal(10, page1.List.Count);
        Assert.Equal(10, page2.List.Count);
        Assert.Equal(5, page3.List.Count);
    }

    /// <summary>
    /// 测试空结果处理
    /// Requirements: 1.6
    /// </summary>
    [Fact]
    public async Task GetMoneyRecords_EmptyResult_ReturnsLastPageOne()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId = 1;

        // Act
        var result = await service.GetMoneyRecordsAsync(userId, 0, 1, 15);

        // Assert
        Assert.Equal(0, result.Total);
        Assert.Equal(1, result.LastPage); // 空结果时 last_page 应为 1
        Assert.Empty(result.List);
    }

    /// <summary>
    /// 测试用户隔离 - 只返回当前用户的记录
    /// Requirements: 1.1-1.4
    /// </summary>
    [Fact]
    public async Task GetMoneyRecords_OnlyReturnsCurrentUserRecords()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateAssetService(dbContext);
        var userId1 = 1;
        var userId2 = 2;

        var records = new List<ProfitMoney>
        {
            new() { UserId = userId1, ChangeMoney = 100, Money = 100, Type = 1, Content = "用户1记录", CreatedAt = DateTime.Now },
            new() { UserId = userId2, ChangeMoney = 200, Money = 200, Type = 1, Content = "用户2记录", CreatedAt = DateTime.Now }
        };
        await dbContext.ProfitMoneys.AddRangeAsync(records);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetMoneyRecordsAsync(userId1, 0, 1, 15);

        // Assert
        Assert.Equal(1, result.Total);
        Assert.Single(result.List);
        Assert.Equal("100", result.List[0].ChangeMoney);
    }
}
