using FluentValidation.TestHelper;
using Microsoft.Extensions.Time.Testing;
using SIGCM2.Application.Pricing.ChargeableChars.SchedulePrice;

namespace SIGCM2.Application.Tests.Pricing.ChargeableChars;

/// <summary>
/// PRC-001 — Validator tests for SchedulePriceChangeCommand.
/// Covers: PricePerUnit > 0, ValidFrom >= today_AR.
/// Forward-only check (ValidFrom > existing.ValidFrom) is done in handler, not validator.
/// </summary>
public class SchedulePriceChangeCommandValidatorTests
{
    private readonly FakeTimeProvider _time = new(new DateTimeOffset(2026, 4, 20, 12, 0, 0, TimeSpan.Zero));
    private readonly SchedulePriceChangeCommandValidator _validator;

    private static readonly DateOnly Today = new(2026, 4, 20);
    private static readonly DateOnly Yesterday = new(2026, 4, 19);
    private static readonly DateOnly Tomorrow = new(2026, 4, 21);

    public SchedulePriceChangeCommandValidatorTests()
    {
        _validator = new SchedulePriceChangeCommandValidator(_time);
    }

    private static SchedulePriceChangeCommand ValidCmd() => new(
        Id: 1L,
        PricePerUnit: 2.0m,
        ValidFrom: Tomorrow);

    // ── PricePerUnit ─────────────────────────────────────────────────────────────

    [Fact]
    public void PricePerUnit_Zero_FailsValidation()
    {
        var cmd = ValidCmd() with { PricePerUnit = 0m };
        _validator.TestValidate(cmd).ShouldHaveValidationErrorFor(x => x.PricePerUnit);
    }

    [Fact]
    public void PricePerUnit_Negative_FailsValidation()
    {
        var cmd = ValidCmd() with { PricePerUnit = -1m };
        _validator.TestValidate(cmd).ShouldHaveValidationErrorFor(x => x.PricePerUnit);
    }

    [Fact]
    public void PricePerUnit_Positive_Passes()
    {
        var cmd = ValidCmd() with { PricePerUnit = 0.01m };
        _validator.TestValidate(cmd).ShouldNotHaveValidationErrorFor(x => x.PricePerUnit);
    }

    // ── ValidFrom ────────────────────────────────────────────────────────────────

    [Fact]
    public void ValidFrom_InPast_FailsValidation()
    {
        var cmd = ValidCmd() with { ValidFrom = Yesterday };
        _validator.TestValidate(cmd).ShouldHaveValidationErrorFor(x => x.ValidFrom);
    }

    [Fact]
    public void ValidFrom_Today_Passes()
    {
        // today is valid — forward-only check vs existing row is done in handler
        var cmd = ValidCmd() with { ValidFrom = Today };
        _validator.TestValidate(cmd).ShouldNotHaveValidationErrorFor(x => x.ValidFrom);
    }

    [Fact]
    public void ValidFrom_Future_Passes()
    {
        var cmd = ValidCmd() with { ValidFrom = Tomorrow };
        _validator.TestValidate(cmd).ShouldNotHaveValidationErrorFor(x => x.ValidFrom);
    }

    // ── Id ───────────────────────────────────────────────────────────────────────

    [Fact]
    public void Id_Zero_FailsValidation()
    {
        var cmd = ValidCmd() with { Id = 0L };
        _validator.TestValidate(cmd).ShouldHaveValidationErrorFor(x => x.Id);
    }

    [Fact]
    public void Id_Positive_Passes()
    {
        var cmd = ValidCmd() with { Id = 1L };
        _validator.TestValidate(cmd).ShouldNotHaveValidationErrorFor(x => x.Id);
    }

    // ── Happy path ────────────────────────────────────────────────────────────────

    [Fact]
    public void ValidCommand_PassesAllRules()
    {
        _validator.TestValidate(ValidCmd()).ShouldNotHaveAnyValidationErrors();
    }
}
