modules/backend/Write-Persistence-EFCore.ps1

param(
    [string]$ProjectName,
    [string]$OrmMode,
    [string]$DbProvider,
    [string]$OutputPath,
    [string[]]$Entities
)

if ($OrmMode -notmatch "EFCore|Hybrid") { return }

. (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\core\Utils.ps1")

$base = Join-Path $OutputPath "src\$ProjectName.Persistence"
function Write-File($rel, $con) { Write-CoreFile (Join-Path $base $rel) $con }
function T($template, $e = "") {
    $res = $template.Replace("{P}", $ProjectName)
    if ($e) { $res = $res.Replace("{E}", $e) }
    return $res
}

# ---- UnitOfWork (T-24) ----
Write-File "UnitOfWork\UnitOfWork.cs" (T @'
using Microsoft.EntityFrameworkCore.Storage;
using {P}.Domain.Interfaces;
using {P}.Persistence.Context;
 
namespace {P}.Persistence.UnitOfWork;
 
public class UnitOfWork : IUnitOfWork
{
    private readonly AppDbContext _context;
    private IDbContextTransaction? _transaction;
 
    public UnitOfWork(AppDbContext context) => _context = context;
 
    public async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
        => await _context.SaveChangesAsync(cancellationToken);
 
    public async Task BeginTransactionAsync()
        => _transaction = await _context.Database.BeginTransactionAsync();
 
    public async Task CommitTransactionAsync()
    {
        if (_transaction is null) return;
        await _transaction.CommitAsync();
        await _transaction.DisposeAsync();
        _transaction = null;
    }
 
    public async Task RollbackTransactionAsync()
    {
        if (_transaction is null) return;
        await _transaction.RollbackAsync();
        await _transaction.DisposeAsync();
        _transaction = null;
    }
 
    public void Dispose() => _context.Dispose();
}
'@
)

if ($OrmMode -eq "EFCore") {
    foreach ($e in $Entities) {
        $pE = Get-Plural $e
        if ($e -eq "User") {
            Write-File "Repositories\UserRepository.cs" (T @'
using Microsoft.EntityFrameworkCore;
using {P}.Domain.Entities;
using {P}.Domain.Interfaces;
using {P}.Persistence.Context;
namespace {P}.Persistence.Repositories;
public class UserRepository : IUserRepository {
    private readonly AppDbContext _context;
    public UserRepository(AppDbContext context) => _context = context;
    public async Task<User?> GetByUsernameAsync(string u) => await _context.Users.FirstOrDefaultAsync(x => x.Username == u);
    public async Task<int> AddAsync(User u) { _context.Users.Add(u); await _context.SaveChangesAsync(); return u.Id; }
}
'@
)
        } else {
            Write-File "Repositories\$e`Repository.cs" (T @'
using Microsoft.EntityFrameworkCore;
using {P}.Domain.Common;
using {P}.Domain.Entities;
using {P}.Domain.Interfaces;
using {P}.Persistence.Context;
namespace {P}.Persistence.Repositories;
public class {E}Repository : I{E}Repository {
    private readonly AppDbContext _ctx;
    public {E}Repository(AppDbContext ctx) => _ctx = ctx;
    public async Task<{E}?> GetByIdAsync(int id) => await _ctx.{PE}.FindAsync(id);
    public async Task<IEnumerable<{E}>> GetAllAsync() => await _ctx.{PE}.ToListAsync();
    public async Task<PagedResult<{E}>> GetPagedAsync(PagedQuery query)
    {
        var total = await _ctx.{PE}.CountAsync();
        var items = await _ctx.{PE}.Skip(query.Skip).Take(query.Size).ToListAsync();
        return new PagedResult<{E}> { Items = items, TotalCount = total, Page = query.Page, Size = query.Size };
    }
    public async Task<int> AddAsync({E} e) { _ctx.{PE}.Add(e); await _ctx.SaveChangesAsync(); return e.Id; }
    public async Task UpdateAsync({E} e) { _ctx.{PE}.Update(e); await _ctx.SaveChangesAsync(); }
    public async Task DeleteAsync(int id) { var e = await GetByIdAsync(id); if(e!=null){ e.IsDeleted = true; e.DeletedAt = DateTime.UtcNow; await _ctx.SaveChangesAsync(); } }
}
'@
 $e | % { $_.Replace("{PE}", $pE) })
        }
    }
}