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") {
    $dbBuildOrImage = if ($OrmMode -eq "Dapper") { " build:`n context: ./sqlserver" } else { " image: mcr.microsoft.com/mssql/server:2022-latest" }
    $dbService = @"
  db:
    container_name: ${p}-db
$dbBuildOrImage
    environment:
      SA_PASSWORD: "YourStrong@Passw0rd"
      ACCEPT_EULA: "Y"
    ports:
      - "1433:1433"
    healthcheck:
      test: ["CMD-SHELL", "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'YourStrong@Passw0rd' -C -Q 'SELECT 1' || exit 1"]
      interval: 5s
      timeout: 5s
      retries: 5
    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: EF Core Migrations & SeedData handle table creation and seed data. init.sql only creates the DB.
# Dapper: No EF migrations, so init.sql creates all tables and seeds data.
$bcryptHash = '$2a$12$4V.u4DaYV9N7BPMkbHBtuO18JGY.AQWcGGb4c39EDBxZz9eQXlZRK'

if ($OrmMode -eq "Dapper") {
    $tables = ""
    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), `"Role`" VARCHAR(50) DEFAULT 'User' NOT NULL, `"IsActive`" BOOLEAN DEFAULT TRUE, `"IsDeleted`" BOOLEAN DEFAULT FALSE, `"DeletedAt`" TIMESTAMP, `"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, `"IsDeleted`" BOOLEAN DEFAULT FALSE, `"DeletedAt`" TIMESTAMP, `"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 [{P}Db].[dbo].[Users] (Id INT IDENTITY(1,1) PRIMARY KEY, Username NVARCHAR(100) NOT NULL UNIQUE, PasswordHash NVARCHAR(256) NOT NULL, Email NVARCHAR(256), Role NVARCHAR(50) DEFAULT 'User' NOT NULL, IsActive BIT DEFAULT 1, IsDeleted BIT DEFAULT 0, DeletedAt DATETIME2, 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 [{P}Db].[dbo].$pE (Id INT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(200) NOT NULL$extraSql, IsDeleted BIT DEFAULT 0, DeletedAt DATETIME2, CreatedAt DATETIME2 DEFAULT GETUTCDATE(), UpdatedAt DATETIME2 DEFAULT GETUTCDATE());`n"
            }
        }
    }

    if ($DbProvider -eq "MSSQL") {
        $seedSql = (T $tables) + (T @'
-- Default Password: Admin123!
IF NOT EXISTS (SELECT 1 FROM [{P}Db].[dbo].[Users] WHERE Username='admin')
    INSERT INTO [{P}Db].[dbo].[Users] (Username, PasswordHash, Email, Role) VALUES ('admin', '$2a$12$4V.u4DaYV9N7BPMkbHBtuO18JGY.AQWcGGb4c39EDBxZz9eQXlZRK', 'admin@example.com', 'Admin');
'@
)
        $initSql = (T @'
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'{P}Db') CREATE DATABASE [{P}Db];
'@
) + "`n" + $seedSql
    } else {
        $initSql = $tables + "`n-- Default Password: Admin123!`nINSERT INTO `"Users`" (`"Username`", `"PasswordHash`", `"Email`", `"Role`") VALUES ('admin', '$bcryptHash', 'admin@example.com', 'Admin') ON CONFLICT (`"Username`") DO NOTHING;"
    }
} else {
    # EFCore & Hybrid modes: database creation only (tables created by EF Core Migrations)
    if ($DbProvider -eq "MSSQL") {
        $initSql = (T @'
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'{P}Db') CREATE DATABASE [{P}Db];
'@
)
    } else {
        $initSql = (T "-- Database {P}Db is automatically created by POSTGRES_DB environment variable.`n-- EF Core Migrations and SeedData manage database schema and initial data.`n")
    }
}

# --- DB-Specific Files ---
if ($DbProvider -eq "MSSQL") {
    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 (-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/"