using System.Data;
using Microsoft.EntityFrameworkCore;
using SolutionErp.Application.Common.Interfaces;
using SolutionErp.Application.PurchaseEvaluations.Services;
using SolutionErp.Domain.PurchaseEvaluations;

namespace SolutionErp.Infrastructure.Services;

// Mirror ContractCodeGenerator pattern — atomic sequence per (year × type).
// Prefix = "PE/{YYYY}/{TypeLetter}".
public class PurchaseEvaluationCodeGenerator(IApplicationDbContext db, IDateTime dateTime)
    : IPurchaseEvaluationCodeGenerator
{
    public async Task<string> GenerateAsync(PurchaseEvaluation evaluation, CancellationToken ct = default)
    {
        var typeLetter = evaluation.Type switch
        {
            PurchaseEvaluationType.DuyetNcc => "A",
            PurchaseEvaluationType.DuyetNccPhuongAn => "B",
            _ => "X",
        };
        var year = dateTime.UtcNow.Year;
        var prefix = $"PE/{year}/{typeLetter}";

        var context = (DbContext)db;
        await using var tx = await context.Database
            .BeginTransactionAsync(IsolationLevel.Serializable, ct);
        try
        {
            var seq = await db.PurchaseEvaluationCodeSequences
                .FirstOrDefaultAsync(s => s.Prefix == prefix, ct);
            if (seq is null)
            {
                seq = new PurchaseEvaluationCodeSequence
                {
                    Prefix = prefix, LastSeq = 1, UpdatedAt = dateTime.UtcNow,
                };
                db.PurchaseEvaluationCodeSequences.Add(seq);
            }
            else
            {
                seq.LastSeq += 1;
                seq.UpdatedAt = dateTime.UtcNow;
            }
            await db.SaveChangesAsync(ct);
            await tx.CommitAsync(ct);
            return $"{prefix}/{seq.LastSeq:D3}";
        }
        catch
        {
            await tx.RollbackAsync(ct);
            throw;
        }
    }
}
