modules/backend/Write-Persistence-Shared.ps1

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

. (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
}

# =====================================================================
# AppDbContext + EF Core entity konfigürasyonları
# =====================================================================
$dbSets = ""
foreach ($e in $Entities) {
        $pE = Get-Plural $e
        $dbSets += " public DbSet<$e> $pE => Set<$e>();`n"

        if ($e -eq "User") {
            # BCrypt hash of "Admin123!" with work factor 12
            $bcryptHash = '$2a$12$4V.u4DaYV9N7BPMkbHBtuO18JGY.AQWcGGb4c39EDBxZz9eQXlZRK'
            Write-File "Configurations\UserConfiguration.cs" (T @"
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using {P}.Domain.Entities;
using {P}.Domain.ValueObjects;
 
namespace {P}.Persistence.Configurations;
 
public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.HasKey(u => u.Id);
        builder.Property(u => u.Username).HasMaxLength(100).IsRequired();
        builder.Property(u => u.Email)
               .HasConversion(
                   email => email.Value,
                   value => new Email(value))
               .HasMaxLength(255)
               .IsRequired();
        builder.HasQueryFilter(u => !u.IsDeleted);
        builder.HasData(new
        {
            Id = 1,
            Username = `"admin`",
            Email = new Email(`"admin@example.com`"),
            PasswordHash = `"$bcryptHash`",
            Role = `"Admin`",
            IsActive = true,
            CreatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            UpdatedAt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            IsDeleted = false
        });
    }
}
"@
)
        } else {
            $extraConfig = if ($e -eq "Product") { "`r`n builder.Property(x => x.Price).HasColumnType(`"decimal(18,2)`").HasDefaultValue(0);" } else { "" }
            Write-File "Configurations\${e}Configuration.cs" (T @"
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using {P}.Domain.Entities;
 
namespace {P}.Persistence.Configurations;
 
public class ${e}Configuration : IEntityTypeConfiguration<$e>
{
    public void Configure(EntityTypeBuilder<$e> builder)
    {
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).HasMaxLength(200).IsRequired();$extraConfig
        builder.HasQueryFilter(x => !x.IsDeleted);
    }
}
"@
 $e)
        }
}

Write-File "Context\AppDbContext.cs" (T @"
using Microsoft.EntityFrameworkCore;
using {P}.Domain.Entities;
 
namespace {P}.Persistence.Context;
 
public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
 
$dbSets
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
    }
}
"@
)

# =====================================================================
# ServiceRegistration
# =====================================================================
$registrations = ""
foreach ($e in $Entities) {
    $registrations += " services.AddScoped<I$e`Repository, $e`Repository>();`n"
}
$useProvider = switch ($DbProvider) {
    "Postgres" { "opt.UseNpgsql(connStr)" }
    default    { "opt.UseSqlServer(connStr)" }
}

Write-File "ServiceRegistration\PersistenceServiceRegistration.cs" (T @"
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using {P}.Domain.Interfaces;
using {P}.Persistence.Context;
using {P}.Persistence.Repositories;
 
namespace {P}.Persistence.ServiceRegistration;
public static class PersistenceServiceRegistration {
    public static IServiceCollection AddPersistenceServices(this IServiceCollection services, IConfiguration configuration) {
        var connStr = configuration.GetConnectionString("DefaultConnection");
        services.AddDbContext<AppDbContext>(opt => $useProvider);
        services.AddScoped<IUnitOfWork, {P}.Persistence.UnitOfWork.UnitOfWork>();
$registrations return services;
    }
}
"@
)