using HoneyBox.Core.Interfaces;
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: 6.1-6.4
/// </summary>
public class CollectionServiceIntegrationTests
{
    private HoneyBoxDbContext CreateInMemoryDbContext()
    {
        var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
            .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
            .Options;

        return new HoneyBoxDbContext(options);
    }

    private CollectionService CreateCollectionService(HoneyBoxDbContext dbContext)
    {
        var mockLogger = new Mock<ILogger<CollectionService>>();
        var mockRedisService = new Mock<IRedisService>();
        mockRedisService.Setup(x => x.DeleteAsync(It.IsAny<string>())).Returns(Task.CompletedTask);
        return new CollectionService(dbContext, mockLogger.Object, mockRedisService.Object);
    }

    #region 收藏功能测试 (Requirements 6.1-6.4)

    /// <summary>
    /// 测试添加收藏
    /// Requirements: 6.1
    /// </summary>
    [Fact]
    public async Task ToggleCollection_AddsCollection_WhenNotCollected()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        var goods = new Good
        {
            Id = 1,
            Title = "测试商品",
            Type = 2,
            Status = 1,
            ShowIs = 0,
            Price = 10,
            Stock = 5,
            ImgUrl = "img.jpg",
            ImgUrlDetail = "detail.jpg"
        };
        await dbContext.Goods.AddAsync(goods);
        await dbContext.SaveChangesAsync();

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

        // Assert
        Assert.True(result);
        var collection = await dbContext.GoodsCollections
            .FirstOrDefaultAsync(c => c.UserId == 100 && c.GoodsId == 1 && c.Num == 1);
        Assert.NotNull(collection);
    }

    /// <summary>
    /// 测试取消收藏
    /// Requirements: 6.2
    /// </summary>
    [Fact]
    public async Task ToggleCollection_RemovesCollection_WhenAlreadyCollected()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        var goods = new Good
        {
            Id = 1,
            Title = "测试商品",
            Type = 2,
            Status = 1,
            ShowIs = 0,
            Price = 10,
            Stock = 5,
            ImgUrl = "img.jpg",
            ImgUrlDetail = "detail.jpg"
        };
        await dbContext.Goods.AddAsync(goods);

        // 添加已有收藏
        var collection = new GoodsCollection
        {
            Id = 1,
            UserId = 100,
            GoodsId = 1,
            Num = 1,
            Type = 2,
            CreatedAt = DateTime.Now
        };
        await dbContext.GoodsCollections.AddAsync(collection);
        await dbContext.SaveChangesAsync();

        // Act - 再次调用应取消收藏
        var result = await service.ToggleCollectionAsync(100, 1, 1);

        // Assert
        Assert.True(result);
        var exists = await dbContext.GoodsCollections
            .AnyAsync(c => c.UserId == 100 && c.GoodsId == 1 && c.Num == 1);
        Assert.False(exists);
    }

    /// <summary>
    /// 测试收藏往返一致性 - 添加后再取消
    /// Requirements: 6.1, 6.2
    /// </summary>
    [Fact]
    public async Task ToggleCollection_RoundTrip_AddsAndRemoves()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        var goods = new Good
        {
            Id = 1,
            Title = "测试商品",
            Type = 2,
            Status = 1,
            ShowIs = 0,
            Price = 10,
            Stock = 5,
            ImgUrl = "img.jpg",
            ImgUrlDetail = "detail.jpg"
        };
        await dbContext.Goods.AddAsync(goods);
        await dbContext.SaveChangesAsync();

        // Act - 第一次调用：添加收藏
        await service.ToggleCollectionAsync(100, 1, 1);
        var afterAdd = await service.IsCollectedAsync(100, 1, 1);

        // Act - 第二次调用：取消收藏
        await service.ToggleCollectionAsync(100, 1, 1);
        var afterRemove = await service.IsCollectedAsync(100, 1, 1);

        // Assert
        Assert.True(afterAdd);
        Assert.False(afterRemove);
    }

    /// <summary>
    /// 测试收藏列表查询
    /// Requirements: 6.4
    /// </summary>
    [Fact]
    public async Task GetCollectionList_ReturnsUserCollections()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        // 添加商品
        var goods = new List<Good>
        {
            new() { Id = 1, Title = "商品1", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 5, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" },
            new() { Id = 2, Title = "商品2", Type = 2, Status = 1, ShowIs = 0, Price = 20, Stock = 10, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" }
        };
        await dbContext.Goods.AddRangeAsync(goods);

        // 添加收藏
        var collections = new List<GoodsCollection>
        {
            new() { Id = 1, UserId = 100, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now },
            new() { Id = 2, UserId = 100, GoodsId = 2, Num = 1, Type = 2, CreatedAt = DateTime.Now }
        };
        await dbContext.GoodsCollections.AddRangeAsync(collections);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetCollectionListAsync(100, 0, 1, 10);

        // Assert
        Assert.NotNull(result);
        Assert.Equal(2, result.Data.Count);
    }

    /// <summary>
    /// 测试收藏列表查询 - 按类型过滤
    /// Requirements: 6.4
    /// </summary>
    [Fact]
    public async Task GetCollectionList_FiltersByType()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        // 添加商品
        var goods = new List<Good>
        {
            new() { Id = 1, Title = "商品1", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 5, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" },
            new() { Id = 2, Title = "商品2", Type = 6, Status = 1, ShowIs = 0, Price = 20, Stock = 10, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" }
        };
        await dbContext.Goods.AddRangeAsync(goods);

        // 添加收藏
        var collections = new List<GoodsCollection>
        {
            new() { Id = 1, UserId = 100, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now },
            new() { Id = 2, UserId = 100, GoodsId = 2, Num = 1, Type = 6, CreatedAt = DateTime.Now }
        };
        await dbContext.GoodsCollections.AddRangeAsync(collections);
        await dbContext.SaveChangesAsync();

        // Act - 只查询类型2的收藏
        var result = await service.GetCollectionListAsync(100, 2, 1, 10);

        // Assert
        Assert.Single(result.Data);
        Assert.Equal(2, result.Data[0].Type);
    }

    /// <summary>
    /// 测试收藏列表查询 - 分页
    /// Requirements: 6.4
    /// </summary>
    [Fact]
    public async Task GetCollectionList_PaginationWorksCorrectly()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        // 添加15个商品和收藏
        var goods = Enumerable.Range(1, 15).Select(i => new Good
        {
            Id = i,
            Title = $"商品{i}",
            Type = 2,
            Status = 1,
            ShowIs = 0,
            Price = i * 10,
            Stock = 10,
            ImgUrl = $"img{i}.jpg",
            ImgUrlDetail = $"detail{i}.jpg"
        }).ToList();
        await dbContext.Goods.AddRangeAsync(goods);

        var collections = Enumerable.Range(1, 15).Select(i => new GoodsCollection
        {
            Id = i,
            UserId = 100,
            GoodsId = i,
            Num = 1,
            Type = 2,
            CreatedAt = DateTime.Now.AddMinutes(-i)
        }).ToList();
        await dbContext.GoodsCollections.AddRangeAsync(collections);
        await dbContext.SaveChangesAsync();

        // Act
        var page1 = await service.GetCollectionListAsync(100, 0, 1, 10);
        var page2 = await service.GetCollectionListAsync(100, 0, 2, 10);

        // Assert
        Assert.Equal(2, page1.LastPage);
        Assert.Equal(10, page1.Data.Count);
        Assert.Equal(5, page2.Data.Count);
    }

    /// <summary>
    /// 测试检查收藏状态
    /// Requirements: 6.1
    /// </summary>
    [Fact]
    public async Task IsCollected_ReturnsCorrectStatus()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        var collection = new GoodsCollection
        {
            Id = 1,
            UserId = 100,
            GoodsId = 1,
            Num = 1,
            Type = 2,
            CreatedAt = DateTime.Now
        };
        await dbContext.GoodsCollections.AddAsync(collection);
        await dbContext.SaveChangesAsync();

        // Act
        var isCollected = await service.IsCollectedAsync(100, 1, 1);
        var isNotCollected = await service.IsCollectedAsync(100, 2, 1);

        // Assert
        Assert.True(isCollected);
        Assert.False(isNotCollected);
    }

    /// <summary>
    /// 测试删除收藏
    /// Requirements: 6.2
    /// </summary>
    [Fact]
    public async Task DeleteCollection_RemovesCollectionById()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        var collection = new GoodsCollection
        {
            Id = 1,
            UserId = 100,
            GoodsId = 1,
            Num = 1,
            Type = 2,
            CreatedAt = DateTime.Now
        };
        await dbContext.GoodsCollections.AddAsync(collection);
        await dbContext.SaveChangesAsync();

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

        // Assert
        Assert.True(result);
        var exists = await dbContext.GoodsCollections.AnyAsync(c => c.Id == 1);
        Assert.False(exists);
    }

    /// <summary>
    /// 测试删除不存在的收藏
    /// Requirements: 6.2
    /// </summary>
    [Fact]
    public async Task DeleteCollection_ThrowsException_WhenNotFound()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        // Act & Assert
        await Assert.ThrowsAsync<InvalidOperationException>(
            () => service.DeleteCollectionAsync(100, 999));
    }

    /// <summary>
    /// 测试收藏商品不存在
    /// Requirements: 6.1
    /// </summary>
    [Fact]
    public async Task ToggleCollection_ThrowsException_WhenGoodsNotFound()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        // Act & Assert
        await Assert.ThrowsAsync<InvalidOperationException>(
            () => service.ToggleCollectionAsync(100, 999, 1));
    }

    /// <summary>
    /// 测试收藏已下架商品
    /// Requirements: 6.1
    /// </summary>
    [Fact]
    public async Task ToggleCollection_ThrowsException_WhenGoodsOffline()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        var goods = new Good
        {
            Id = 1,
            Title = "下架商品",
            Type = 2,
            Status = 0, // 下架
            ShowIs = 0,
            Price = 10,
            Stock = 5,
            ImgUrl = "img.jpg",
            ImgUrlDetail = "detail.jpg"
        };
        await dbContext.Goods.AddAsync(goods);
        await dbContext.SaveChangesAsync();

        // Act & Assert
        await Assert.ThrowsAsync<InvalidOperationException>(
            () => service.ToggleCollectionAsync(100, 1, 1));
    }

    /// <summary>
    /// 测试用户隔离 - 只返回当前用户的收藏
    /// Requirements: 6.4
    /// </summary>
    [Fact]
    public async Task GetCollectionList_OnlyReturnsCurrentUserCollections()
    {
        // Arrange
        var dbContext = CreateInMemoryDbContext();
        var service = CreateCollectionService(dbContext);

        // 添加商品
        var goods = new Good
        {
            Id = 1,
            Title = "商品1",
            Type = 2,
            Status = 1,
            ShowIs = 0,
            Price = 10,
            Stock = 5,
            ImgUrl = "img1.jpg",
            ImgUrlDetail = "detail1.jpg"
        };
        await dbContext.Goods.AddAsync(goods);

        // 添加不同用户的收藏
        var collections = new List<GoodsCollection>
        {
            new() { Id = 1, UserId = 100, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now },
            new() { Id = 2, UserId = 200, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now }
        };
        await dbContext.GoodsCollections.AddRangeAsync(collections);
        await dbContext.SaveChangesAsync();

        // Act
        var result = await service.GetCollectionListAsync(100, 0, 1, 10);

        // Assert
        Assert.Single(result.Data);
        Assert.Equal(1, result.Data[0].GoodsId);
    }

    #endregion
}
