// ============================================================
// TEST TEMPLATE
// Generated by MORPH Framework
// ============================================================

using FluentAssertions;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;

namespace MyProject.Tests.Unit.Features.{Feature};

/// <summary>
/// Unit tests for {Feature}Service.
/// </summary>
public class {Feature}ServiceTests
{
    private readonly I{Feature}Repository _repository;
    private readonly ILogger<{Feature}Service> _logger;
    private readonly {Feature}Service _sut;

    public {Feature}ServiceTests()
    {
        _repository = Substitute.For<I{Feature}Repository>();
        _logger = Substitute.For<ILogger<{Feature}Service>>();
        _sut = new {Feature}Service(_repository, _logger);
    }

    #region GetByIdAsync Tests

    [Fact]
    public async Task GetByIdAsync_WithValidId_ReturnsDto()
    {
        // Arrange
        var id = 1;
        var entity = CreateTestEntity(id, "Test {Feature}");
        _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
            .Returns(entity);

        // Act
        var result = await _sut.GetByIdAsync(id);

        // Assert
        result.Should().NotBeNull();
        result!.Id.Should().Be(id);
        result.Name.Should().Be("Test {Feature}");
    }

    [Fact]
    public async Task GetByIdAsync_WithInvalidId_ReturnsNull()
    {
        // Arrange
        var id = 999;
        _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
            .Returns((Domain.Entities.{Feature}?)null);

        // Act
        var result = await _sut.GetByIdAsync(id);

        // Assert
        result.Should().BeNull();
    }

    #endregion

    #region GetAllAsync Tests

    [Fact]
    public async Task GetAllAsync_ReturnsAllItems()
    {
        // Arrange
        var entities = new List<Domain.Entities.{Feature}>
        {
            CreateTestEntity(1, "First"),
            CreateTestEntity(2, "Second"),
            CreateTestEntity(3, "Third")
        };
        _repository.GetAllAsync(Arg.Any<CancellationToken>())
            .Returns(entities);

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

        // Assert
        result.Should().HaveCount(3);
        result[0].Name.Should().Be("First");
    }

    [Fact]
    public async Task GetAllAsync_WithNoItems_ReturnsEmptyList()
    {
        // Arrange
        _repository.GetAllAsync(Arg.Any<CancellationToken>())
            .Returns(new List<Domain.Entities.{Feature}>());

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

        // Assert
        result.Should().BeEmpty();
    }

    #endregion

    #region CreateAsync Tests

    [Fact]
    public async Task CreateAsync_WithValidRequest_CreatesAndReturnsDto()
    {
        // Arrange
        var request = new Create{Feature}Request("New {Feature}");

        _repository
            .When(x => x.AddAsync(Arg.Any<Domain.Entities.{Feature}>(), Arg.Any<CancellationToken>()))
            .Do(x =>
            {
                // Simulate ID assignment
                var entity = x.Arg<Domain.Entities.{Feature}>();
                // entity.Id would be set by EF Core
            });

        // Act
        var result = await _sut.CreateAsync(request);

        // Assert
        result.Should().NotBeNull();
        result.Name.Should().Be("New {Feature}");

        await _repository.Received(1).AddAsync(Arg.Any<Domain.Entities.{Feature}>(), Arg.Any<CancellationToken>());
        await _repository.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
    }

    [Theory]
    [InlineData("")]
    [InlineData(" ")]
    [InlineData(null)]
    public async Task CreateAsync_WithInvalidName_ThrowsValidationException(string? name)
    {
        // Arrange
        var request = new Create{Feature}Request(name!);

        // Act
        var act = async () => await _sut.CreateAsync(request);

        // Assert
        await act.Should().ThrowAsync<ValidationException>();
    }

    #endregion

    #region UpdateAsync Tests

    [Fact]
    public async Task UpdateAsync_WithValidRequest_UpdatesEntity()
    {
        // Arrange
        var id = 1;
        var entity = CreateTestEntity(id, "Original");
        var request = new Update{Feature}Request("Updated");

        _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
            .Returns(entity);

        // Act
        await _sut.UpdateAsync(id, request);

        // Assert
        _repository.Received(1).Update(Arg.Any<Domain.Entities.{Feature}>());
        await _repository.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
    }

    [Fact]
    public async Task UpdateAsync_WithNonExistentId_ThrowsNotFoundException()
    {
        // Arrange
        var id = 999;
        var request = new Update{Feature}Request("Updated");

        _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
            .Returns((Domain.Entities.{Feature}?)null);

        // Act
        var act = async () => await _sut.UpdateAsync(id, request);

        // Assert
        await act.Should().ThrowAsync<{Feature}NotFoundException>();
    }

    #endregion

    #region DeleteAsync Tests

    [Fact]
    public async Task DeleteAsync_WithValidId_DeletesEntity()
    {
        // Arrange
        var id = 1;
        var entity = CreateTestEntity(id, "To Delete");

        _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
            .Returns(entity);

        // Act
        await _sut.DeleteAsync(id);

        // Assert
        _repository.Received(1).Remove(entity);
        await _repository.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
    }

    [Fact]
    public async Task DeleteAsync_WithNonExistentId_ThrowsNotFoundException()
    {
        // Arrange
        var id = 999;

        _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
            .Returns((Domain.Entities.{Feature}?)null);

        // Act
        var act = async () => await _sut.DeleteAsync(id);

        // Assert
        await act.Should().ThrowAsync<{Feature}NotFoundException>();
    }

    #endregion

    #region Helper Methods

    private static Domain.Entities.{Feature} CreateTestEntity(int id, string name)
    {
        return Domain.Entities.{Feature}.Create(name);
        // Note: In real tests, you might need reflection to set the Id
        // or use a factory method that accepts an id for testing
    }

    #endregion
}
