modules/backend/Write-Persistence-Hybrid.ps1

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

if ($OrmMode -ne "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
}

function Get-IdentitySql {
    param($table, $cols, $vals)
    switch ($DbProvider) {
        "Postgres" { "INSERT INTO $table ($cols) VALUES ($vals) RETURNING Id" }
        default    { "INSERT INTO $table ($cols) VALUES ($vals) OUTPUT INSERTED.Id" }
    }
}

foreach ($e in $Entities) {
    $pE = Get-Plural $e
    if ($e -eq "User") {
        # Hybrid mode uses Dapper for User (usually)
        $userSql = Get-IdentitySql "Users" "Username, PasswordHash, Email, IsActive, CreatedAt, UpdatedAt" "@Username, @PasswordHash, @Email, @IsActive, @CreatedAt, @UpdatedAt"
        Write-File "Repositories\UserRepository.cs" (T @"
using System.Data;
using Dapper;
using {P}.Domain.Entities;
using {P}.Domain.Interfaces;
namespace {P}.Persistence.Repositories;
public class UserRepository : IUserRepository {
    private readonly IDbConnection _connection;
    public UserRepository(IDbConnection connection) => _connection = connection;
    public async Task<User?> GetByUsernameAsync(string u) => await _connection.QueryFirstOrDefaultAsync<User>("SELECT * FROM Users WHERE Username=@u", new { u });
    public async Task<int> AddAsync(User u) => await _connection.ExecuteScalarAsync<int>("$userSql", u);
}
"@
)
    } else {
        $p = if ($e -eq "Product") { ", Price" } else { "" }
        $v = if ($e -eq "Product") { ", @Price" } else { "" }
        $u = if ($e -eq "Product") { ", Price=@Price" } else { "" }
        $sql = Get-IdentitySql $pE "Name, CreatedAt, UpdatedAt$p" "@Name, @CreatedAt, @UpdatedAt$v"

        Write-File "Repositories\$e`Repository.cs" (T @'
using System.Data;
using Dapper;
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; private readonly IDbConnection _conn;
    public {E}Repository(AppDbContext ctx, IDbConnection conn) { _ctx = ctx; _conn = conn; }
    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) => await _conn.ExecuteScalarAsync<int>(BTICK $sqlBTICK, e);
    public async Task UpdateAsync({E} e) => await _conn.ExecuteAsync(BTICK UPDATE {PE} SET Name=@Name, UpdatedAt=@UpdatedAt$sqlUpdate WHERE Id=@IdBTICK, e);
    public async Task DeleteAsync(int id) {
        var entity = await _ctx.{PE}.FindAsync(id);
        if (entity != null) { entity.Delete(); await _ctx.SaveChangesAsync(); }
    }
}
'@
 $e | % {
    $_.Replace("{PE}", $pE).Replace("{P}", $ProjectName).Replace("BTICK", "`"").Replace('$sql', $sql).Replace('$sqlUpdate', $u)
})
    }
}