using SolutionErp.Domain.PurchaseEvaluations;
using SolutionErp.Infrastructure.Services;
using SolutionErp.Infrastructure.Tests.Common;

namespace SolutionErp.Infrastructure.Tests.Services;

// Tests cho PurchaseEvaluationCodeGenerator — format `PE/{YYYY}/{TypeLetter}/{Seq:D3}`.
// Sequence per year × type: A và B độc lập, sang năm reset cả 2.

public class PurchaseEvaluationCodeGeneratorTests
{
    private static (PurchaseEvaluationCodeGenerator gen, SqliteDbFixture fix, FixedDateTime dt)
        CreateGenerator(int year = 2026)
    {
        var fix = new SqliteDbFixture();
        var dt = new FixedDateTime(new DateTime(year, 6, 15, 0, 0, 0, DateTimeKind.Utc));
        var gen = new PurchaseEvaluationCodeGenerator(fix.Db, dt);
        return (gen, fix, dt);
    }

    // ===== Format =====

    [Theory]
    [InlineData(PurchaseEvaluationType.DuyetNcc, "A")]
    [InlineData(PurchaseEvaluationType.DuyetNccPhuongAn, "B")]
    public async Task Generate_FirstPhieu_FormatMatches(PurchaseEvaluationType type, string expectedLetter)
    {
        var (gen, fix, _) = CreateGenerator(year: 2026);
        using (fix)
        {
            var pe = new PurchaseEvaluation { Type = type };
            var code = await gen.GenerateAsync(pe);
            // Expected: PE/2026/A/001 hoặc PE/2026/B/001
            code.Should().Be($"PE/2026/{expectedLetter}/001");
        }
    }

    [Fact]
    public async Task Generate_SeqIs3DigitPadded()
    {
        var (gen, fix, _) = CreateGenerator(year: 2026);
        using (fix)
        {
            var pe = new PurchaseEvaluation { Type = PurchaseEvaluationType.DuyetNcc };
            // Generate 12 phiếu — kiểm tra padding D3
            string? lastCode = null;
            for (int i = 0; i < 12; i++)
                lastCode = await gen.GenerateAsync(pe);

            lastCode.Should().Be("PE/2026/A/012");
        }
    }

    // ===== A vs B independent sequences =====

    [Fact]
    public async Task Generate_TypeA_And_TypeB_HaveIndependentSequences()
    {
        var (gen, fix, _) = CreateGenerator(year: 2026);
        using (fix)
        {
            var peA = new PurchaseEvaluation { Type = PurchaseEvaluationType.DuyetNcc };
            var peB = new PurchaseEvaluation { Type = PurchaseEvaluationType.DuyetNccPhuongAn };

            var a1 = await gen.GenerateAsync(peA);
            var b1 = await gen.GenerateAsync(peB);
            var a2 = await gen.GenerateAsync(peA);
            var b2 = await gen.GenerateAsync(peB);

            a1.Should().Be("PE/2026/A/001");
            a2.Should().Be("PE/2026/A/002");
            b1.Should().Be("PE/2026/B/001");
            b2.Should().Be("PE/2026/B/002");
        }
    }

    // ===== Year boundary =====

    [Fact]
    public async Task Generate_YearChange_ResetsBothA_And_B_Sequences()
    {
        var (gen, fix, dt) = CreateGenerator(year: 2026);
        using (fix)
        {
            var peA = new PurchaseEvaluation { Type = PurchaseEvaluationType.DuyetNcc };
            var peB = new PurchaseEvaluation { Type = PurchaseEvaluationType.DuyetNccPhuongAn };

            await gen.GenerateAsync(peA);   // PE/2026/A/001
            await gen.GenerateAsync(peA);   // PE/2026/A/002
            await gen.GenerateAsync(peB);   // PE/2026/B/001

            dt.UtcNow = new DateTime(2027, 1, 5, 0, 0, 0, DateTimeKind.Utc);

            var a2027 = await gen.GenerateAsync(peA);
            var b2027 = await gen.GenerateAsync(peB);
            a2027.Should().Be("PE/2027/A/001");
            b2027.Should().Be("PE/2027/B/001");
        }
    }

    // ===== Persistence row =====

    [Fact]
    public async Task Generate_PersistsSequenceRow_PrefixIsKey()
    {
        var (gen, fix, _) = CreateGenerator(year: 2026);
        using (fix)
        {
            var peA = new PurchaseEvaluation { Type = PurchaseEvaluationType.DuyetNcc };
            await gen.GenerateAsync(peA);
            await gen.GenerateAsync(peA);
            await gen.GenerateAsync(peA);

            var seq = fix.Db.PurchaseEvaluationCodeSequences.Single(s => s.Prefix == "PE/2026/A");
            seq.LastSeq.Should().Be(3);
        }
    }
}
