using API.Database;
using API.Models.Internal.Altersgruppen;
using API.Repository.AgeGroupRepo;
using Microsoft.EntityFrameworkCore;

namespace API.Tests.Services;

public class AgeGroupServiceTests : IDisposable
{
    private readonly ApplicationDbContext _context;
    private readonly AgeGroupService _service;

    public AgeGroupServiceTests()
    {
        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
            .Options;

        _context = new ApplicationDbContext(options);
        _service = new AgeGroupService(_context);
    }

    public void Dispose()
    {
        _context.Database.EnsureDeleted();
        _context.Dispose();
    }

    [Fact]
    public async Task GetAllAsync_EmptyDatabase_ReturnsEmptyList()
    {
        // Act
        var result = await _service.GetAllAsync();

        // Assert
        Assert.NotNull(result);
        Assert.Empty(result);
    }

    [Fact]
    public async Task GetAllAsync_WithData_ReturnsAllGroups()
    {
        // Arrange
        var group1 = new AltersGruppe { Name = "U10", StartingAge = 8, EndingAge = 10 };
        var group2 = new AltersGruppe { Name = "U12", StartingAge = 10, EndingAge = 12 };
        await _context.Altersgruppen.AddRangeAsync(group1, group2);
        await _context.SaveChangesAsync();

        // Act
        var result = await _service.GetAllAsync();

        // Assert
        Assert.Equal(2, result.Count);
        Assert.Contains(result, g => g.Name == "U10");
        Assert.Contains(result, g => g.Name == "U12");
    }

    [Fact]
    public async Task GetAsync_ExistingId_ReturnsGroup()
    {
        // Arrange
        var group = new AltersGruppe { Name = "U14", StartingAge = 12, EndingAge = 14 };
        await _context.Altersgruppen.AddAsync(group);
        await _context.SaveChangesAsync();

        // Act
        var result = await _service.GetAsync(group.Id);

        // Assert
        Assert.NotNull(result);
        Assert.Equal("U14", result.Name);
        Assert.Equal(12, result.StartingAge);
        Assert.Equal(14, result.EndingAge);
    }

    [Fact]
    public async Task GetAsync_NonExistingId_ReturnsNull()
    {
        // Act
        var result = await _service.GetAsync("nonexistent-id");

        // Assert
        Assert.Null(result);
    }

    [Fact]
    public async Task CreateAsync_ValidGroup_AddsToDatabase()
    {
        // Arrange
        var newGroup = new AltersGruppe { Name = "U16", StartingAge = 14, EndingAge = 16 };

        // Act
        var result = await _service.CreateAsync(newGroup);

        // Assert
        Assert.NotNull(result);
        Assert.Equal("U16", result.Name);

        var dbGroup = await _context.Altersgruppen.FindAsync(result.Id);
        Assert.NotNull(dbGroup);
        Assert.Equal("U16", dbGroup.Name);
    }

    [Fact]
    public async Task UpdateAsync_ExistingGroup_UpdatesProperties()
    {
        // Arrange
        var group = new AltersGruppe { Name = "U18", StartingAge = 16, EndingAge = 18 };
        await _context.Altersgruppen.AddAsync(group);
        await _context.SaveChangesAsync();

        var updatedGroup = new AltersGruppe { Name = "U18 Updated", StartingAge = 15, EndingAge = 18 };

        // Act
        var result = await _service.UpdateAsync(group.Id, updatedGroup);

        // Assert
        Assert.NotNull(result);
        Assert.Equal("U18 Updated", result.Name);
        Assert.Equal(15, result.StartingAge);
        Assert.Equal(18, result.EndingAge);

        var dbGroup = await _context.Altersgruppen.FindAsync(group.Id);
        Assert.NotNull(dbGroup);
        Assert.Equal("U18 Updated", dbGroup.Name);
    }

    [Fact]
    public async Task UpdateAsync_NonExistingGroup_ReturnsNull()
    {
        // Arrange
        var updatedGroup = new AltersGruppe { Name = "U18 Updated", StartingAge = 15, EndingAge = 18 };

        // Act
        var result = await _service.UpdateAsync("nonexistent-id", updatedGroup);

        // Assert
        Assert.Null(result);
    }

    [Fact]
    public async Task DeleteAsync_ExistingGroup_RemovesFromDatabase()
    {
        // Arrange
        var group = new AltersGruppe { Name = "U20", StartingAge = 18, EndingAge = 20 };
        await _context.Altersgruppen.AddAsync(group);
        await _context.SaveChangesAsync();

        // Act
        var result = await _service.DeleteAsync(group.Id);

        // Assert
        Assert.NotNull(result);
        Assert.Equal("U20", result.Name);

        var dbGroup = await _context.Altersgruppen.FindAsync(group.Id);
        Assert.Null(dbGroup);
    }

    [Fact]
    public async Task DeleteAsync_NonExistingGroup_ReturnsNull()
    {
        // Act
        var result = await _service.DeleteAsync("nonexistent-id");

        // Assert
        Assert.Null(result);
    }
}
