using SIGCM2.Domain.Entities;

namespace SIGCM2.Application.Tests.Domain;

public class PuntoDeVentaTests
{
    private static PuntoDeVenta MakePdv(
        int id = 1,
        int medioId = 5,
        short numeroAFIP = 1,
        string nombre = "PdV Central",
        string? descripcion = null,
        bool activo = true)
        => new(id, medioId, numeroAFIP, nombre, descripcion, activo, DateTime.UtcNow, null);

    // ── ForCreation ───────────────────────────────────────────────────────────

    [Fact]
    public void ForCreation_SetsCorrectValues()
    {
        var pdv = PuntoDeVenta.ForCreation(medioId: 5, numeroAFIP: 3, nombre: "PdV Sur", descripcion: null);

        Assert.Equal(0, pdv.Id);
        Assert.Equal(5, pdv.MedioId);
        Assert.Equal(3, pdv.NumeroAFIP);
        Assert.Equal("PdV Sur", pdv.Nombre);
        Assert.Null(pdv.Descripcion);
        Assert.True(pdv.Activo);
    }

    [Fact]
    public void ForCreation_WithDescripcion_SetsDescripcion()
    {
        var pdv = PuntoDeVenta.ForCreation(5, 1, "PdV Norte", "Descripcion larga");

        Assert.Equal("Descripcion larga", pdv.Descripcion);
    }

    // ── WithUpdatedProfile ────────────────────────────────────────────────────

    [Fact]
    public void WithUpdatedProfile_ReturnsNewInstanceWithUpdatedFields()
    {
        var original = MakePdv(id: 10, nombre: "Original");

        var updated = original.WithUpdatedProfile(nombre: "Actualizado", numeroAFIP: 7, descripcion: "Desc", now: DateTime.UtcNow);

        Assert.NotSame(original, updated);
        Assert.Equal("Actualizado", updated.Nombre);
        Assert.Equal(7, updated.NumeroAFIP);
        Assert.Equal("Desc", updated.Descripcion);
    }

    [Fact]
    public void WithUpdatedProfile_ImmutableFields_Preserved()
    {
        var original = MakePdv(id: 10, medioId: 5);

        var updated = original.WithUpdatedProfile("Nuevo", 2, null, DateTime.UtcNow);

        Assert.Equal(10, updated.Id);
        Assert.Equal(5, updated.MedioId);
        Assert.Equal(original.Activo, updated.Activo);
        Assert.Equal(original.FechaCreacion, updated.FechaCreacion);
    }

    [Fact]
    public void WithUpdatedProfile_SetsFechaModificacion()
    {
        var original = MakePdv();

        var updated = original.WithUpdatedProfile("Nuevo", 2, null, DateTime.UtcNow);

        Assert.NotNull(updated.FechaModificacion);
    }

    // ── WithActivo ────────────────────────────────────────────────────────────

    [Fact]
    public void WithActivo_False_ReturnsDomainObjectWithActivoFalse()
    {
        var pdv = MakePdv(activo: true);

        var deactivated = pdv.WithActivo(false, DateTime.UtcNow);

        Assert.False(deactivated.Activo);
        Assert.NotSame(pdv, deactivated);
    }

    [Fact]
    public void WithActivo_True_ReturnsDomainObjectWithActivoTrue()
    {
        var pdv = MakePdv(activo: false);

        var reactivated = pdv.WithActivo(true, DateTime.UtcNow);

        Assert.True(reactivated.Activo);
    }

    [Fact]
    public void WithActivo_ImmutableFields_Preserved()
    {
        var pdv = MakePdv(id: 99, medioId: 3);

        var toggled = pdv.WithActivo(false, DateTime.UtcNow);

        Assert.Equal(99, toggled.Id);
        Assert.Equal(3, toggled.MedioId);
        Assert.Equal(pdv.NumeroAFIP, toggled.NumeroAFIP);
        Assert.Equal(pdv.Nombre, toggled.Nombre);
    }

    // ── Constructor sets all properties ───────────────────────────────────────

    [Fact]
    public void Constructor_SetsAllProperties()
    {
        var now = DateTime.UtcNow;
        var pdv = new PuntoDeVenta(
            id: 7,
            medioId: 3,
            numeroAFIP: 4,
            nombre: "PdV Test",
            descripcion: "Desc Test",
            activo: true,
            fechaCreacion: now,
            fechaModificacion: null);

        Assert.Equal(7, pdv.Id);
        Assert.Equal(3, pdv.MedioId);
        Assert.Equal(4, pdv.NumeroAFIP);
        Assert.Equal("PdV Test", pdv.Nombre);
        Assert.Equal("Desc Test", pdv.Descripcion);
        Assert.True(pdv.Activo);
        Assert.Equal(now, pdv.FechaCreacion);
        Assert.Null(pdv.FechaModificacion);
    }
}
