modules/devops/Write-Docker.ps1

param(
    [string]$ProjectName,
    [string]$OrmMode,
    [string]$DbProvider,
    [string]$OutputPath,
    [string]$FrontendMode,
    [string[]]$Entities,
    [switch]$SkipFrontend,
    [bool]$Observability = $false,
    [string]$Platform = "Web"
)

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

$dockerRoot = Join-Path $OutputPath "$ProjectName-docker"
if (-not $Global:DryRun -and -not (Test-Path $dockerRoot)) {
    New-Item -ItemType Directory -Path $dockerRoot -Force | Out-Null
}

function Write-File($f, $c) { Write-CoreFile (Join-Path $dockerRoot $f) $c }
function T($t) { $t.Replace("{P}", $ProjectName) }

$p = $ProjectName.ToLower()

# --- Connection String Helper ---
$dockerConnStr = switch ($DbProvider) {
    "Postgres" { "Host=db;Database=${ProjectName}Db;Username=postgres;Password=postgres" }
    default    { "Server=db,1433;Database=${ProjectName}Db;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True;" }
}

# --- Database Service Definition ---
$dbService = ""
if ($DbProvider -eq "MSSQL") {
    $dbService = @"
  db:
    container_name: ${p}-db
    build:
      context: ./sqlserver
    environment:
      SA_PASSWORD: "YourStrong@Passw0rd"
      ACCEPT_EULA: "Y"
    ports:
      - "1433:1433"
    healthcheck:
      test: ["CMD", "/opt/mssql-tools18/bin/sqlcmd", "-S", "localhost", "-U", "sa", "-P", "YourStrong@Passw0rd", "-Q", "SELECT 1", "-No"]
      interval: 10s
      timeout: 5s
      retries: 10
    volumes:
      - ${p}_data:/var/opt/mssql
"@

} elseif ($DbProvider -eq "Postgres") {
    $dbService = @"
  db:
    container_name: ${p}-db
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ${ProjectName}Db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d ${ProjectName}Db"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - ${p}_data:/var/lib/postgresql/data
      - ./postgresql/init.sql:/docker-entrypoint-initdb.d/init.sql
"@

}

# --- docker-compose.yml ---
$dockerComposeContent = @"
services:
$dbService
 
  api:
    container_name: ${p}-api
    build:
      context: ../$ProjectName-backend
      dockerfile: src/$ProjectName.WebApi/Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ConnectionStrings__DefaultConnection=$dockerConnStr
      - Jwt__Key=your-super-secret-key-min-32-characters!!
      - Jwt__Issuer=${ProjectName}Api
      - Jwt__Audience=${ProjectName}Client
    ports:
      - "8080:8080"
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health || exit 1"]
      interval: 15s
      timeout: 10s
      retries: 5
      start_period: 30s
    depends_on:
      db:
        condition: service_healthy
"@


if (-not $SkipFrontend -and $Platform -match "Web|Both") {
    $uiExternalPort = 3000
    $uiInternalPort = 80
    $uiContext = "../$ProjectName-web"
    
    $dockerComposeContent += @"
 
  ui:
    container_name: ${p}-ui
    build:
      context: $uiContext
      dockerfile: Dockerfile
    env_file:
      - $uiContext/.env.docker
    ports:
      - "${uiExternalPort}:${uiInternalPort}"
    depends_on:
      api:
        condition: service_healthy
"@

}

$dockerComposeContent += "`n`nvolumes:`n ${p}_data:"
Write-File "docker-compose.yml" $dockerComposeContent

# --- docker-compose.override.yml (Seq for Observability) ---
if ($Observability) {
    $override = @"
services:
  seq:
    image: datalust/seq:latest
    environment:
      ACCEPT_EULA: Y
    ports:
      - "5341:80"
      - "5342:5341"
 
  api:
    environment:
      - Serilog__WriteTo__0__Args__serverUrl=http://seq:5341
"@

    Write-File "docker-compose.override.yml" $override
}

# --- SQL Scripts ---
# EFCore/Hybrid: migration tabloları ve seed'i yönetir, init.sql sadece DB oluşturur
# Dapper: migration yok, init.sql tüm yapıyı kurar (idempotent)
$isDapper = ($OrmMode -eq "Dapper")
$bcryptHash = '$2a$11$K5L4eU5vU9.KUjFp3q/WyOFq1JBk5NbMgFV2aSvZCjfTKzf6zSmKS'

$tables = ""
if ($isDapper) {
    foreach ($e in $Entities) {
        $pE = Get-Plural $e
        $extraSql = if ($e -eq "Product") { ", Price DECIMAL(18,2) DEFAULT 0" } else { "" }

        if ($DbProvider -eq "Postgres") {
            if ($e -eq "User") {
                $tables += "CREATE TABLE IF NOT EXISTS Users (Id SERIAL PRIMARY KEY, Username VARCHAR(100) NOT NULL UNIQUE, PasswordHash VARCHAR(256) NOT NULL, Email VARCHAR(256), IsActive BOOLEAN DEFAULT TRUE, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UpdatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP);`n"
            } else {
                $tables += "CREATE TABLE IF NOT EXISTS $pE (Id SERIAL PRIMARY KEY, Name VARCHAR(200) NOT NULL$extraSql, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UpdatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP);`n"
            }
        } else {
            if ($e -eq "User") {
                $tables += "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='Users' AND xtype='U') CREATE TABLE Users (Id INT IDENTITY(1,1) PRIMARY KEY, Username NVARCHAR(100) NOT NULL UNIQUE, PasswordHash NVARCHAR(256) NOT NULL, Email NVARCHAR(256), IsActive BIT DEFAULT 1, CreatedAt DATETIME2 DEFAULT GETUTCDATE(), UpdatedAt DATETIME2 DEFAULT GETUTCDATE());`n"
            } else {
                $tables += "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='$pE' AND xtype='U') CREATE TABLE $pE (Id INT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(200) NOT NULL$extraSql, CreatedAt DATETIME2 DEFAULT GETUTCDATE(), UpdatedAt DATETIME2 DEFAULT GETUTCDATE());`n"
            }
        }
    }
}

# --- DB-Specific Files ---
if ($DbProvider -eq "MSSQL") {
    $seedSql = if ($isDapper) {
        # Dapper: tablo + idempotent seed
        $tables + @'
GO
-- Default Password: Admin123!
IF NOT EXISTS (SELECT 1 FROM Users WHERE Username='admin')
    INSERT INTO Users (Username, PasswordHash, Email) VALUES ('admin', '$2a$11$K5L4eU5vU9.KUjFp3q/WyOFq1JBk5NbMgFV2aSvZCjfTKzf6zSmKS', 'admin@example.com');
GO
'@

    } else {
        # EFCore/Hybrid: sadece DB olustur, migration halleder
        ""
    }

    $initSql = (T @'
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'{P}Db') CREATE DATABASE [{P}Db];
GO
USE [{P}Db];
GO
'@
) + "`n" + $seedSql

    if (-not $Global:DryRun) {
        New-Item -ItemType Directory -Path (Join-Path $dockerRoot "sqlserver") -Force | Out-Null
    }
    Write-CoreFile (Join-Path $dockerRoot "sqlserver\Dockerfile") "FROM mcr.microsoft.com/mssql/server:2022-latest`nENV ACCEPT_EULA=Y`nENV SA_PASSWORD=`"YourStrong@Passw0rd`"`nCOPY init.sql /init.sql`nCOPY --chmod=755 entrypoint.sh /entrypoint.sh`nENTRYPOINT [`"/entrypoint.sh`"]"
    Write-CoreFile (Join-Path $dockerRoot "sqlserver\entrypoint.sh") (T "#!/bin/bash`n/opt/mssql/bin/sqlservr &`nsleep 30`n/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P `"YourStrong@Passw0rd`" -i /init.sql -No`nwait")
    Write-CoreFile (Join-Path $dockerRoot "sqlserver\init.sql") $initSql

} elseif ($DbProvider -eq "Postgres") {
    if ($isDapper) {
        # Dapper: tablo + idempotent seed
        $initSql = $tables + "`n-- Default Password: Admin123!`nINSERT INTO Users (Username, PasswordHash, Email) VALUES ('admin', '$bcryptHash', 'admin@example.com') ON CONFLICT (Username) DO NOTHING;"
    } else {
        # EFCore/Hybrid: sadece bos dosya, migration halleder
        $initSql = "-- EFCore migrations will create tables and seed data`n"
    }
    if (-not $Global:DryRun) {
        New-Item -ItemType Directory -Path (Join-Path $dockerRoot "postgresql") -Force | Out-Null
    }
    Write-CoreFile (Join-Path $dockerRoot "postgresql\init.sql") $initSql
}

# --- Write .gitignore at the main OutputPath ---
Write-CoreFile (Join-Path $OutputPath ".gitignore") "bin/`nobj/`n*.user`n.vs/`n*.log`n.data/`n*.db`n.env`nnode_modules/`ndist/`n.expo/"