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

namespace SolutionErp.Infrastructure.Services;

// Mirror ContractCodeGenerator + PurchaseEvaluationCodeGenerator pattern.
// Format: "NV/{YYYY}/{Seq:D4}", reset per năm.
//
// SERIALIZABLE transaction tránh race khi 2 admin tạo NV đồng thời.
public class EmployeeCodeGenerator(IApplicationDbContext db, IDateTime dateTime)
    : IEmployeeCodeGenerator
{
    public async Task<string> GenerateAsync(CancellationToken ct = default)
    {
        var year = dateTime.UtcNow.Year;
        var prefix = $"NV/{year}";

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