# Open Digital Product Factory  first-time setup script (Windows PowerShell)
# Run from the project root: .\scripts\setup.ps1

$ErrorActionPreference = "Stop"

function Write-Step  { param($msg) Write-Host "`n-> $msg" -ForegroundColor Yellow }
function Write-Ok    { param($msg) Write-Host "  v $msg" -ForegroundColor Green }
function Write-Warn  { param($msg) Write-Host "  ! $msg" -ForegroundColor Yellow }
function Write-Fail  { param($msg) Write-Host "  X $msg" -ForegroundColor Red; exit 1 }

Write-Host ""
Write-Host "  Open Digital Product Factory -- Setup" -ForegroundColor Cyan
Write-Host "  ======================================" -ForegroundColor Cyan

# -- Prerequisites ---------------------------------------------------------------

Write-Step "Checking prerequisites"

if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
    Write-Fail "Docker is not installed. Install Docker Desktop: https://www.docker.com/products/docker-desktop/"
}
Write-Ok "Docker found: $(docker --version)"

if (-not (Get-Command node -ErrorAction SilentlyContinue)) {
    Write-Fail "Node.js is not installed. Download v20+ from: https://nodejs.org/"
}
$nodeVersion = [int]((node -v).TrimStart('v').Split('.')[0])
if ($nodeVersion -lt 20) {
    Write-Fail "Node.js v20+ required. Current: $(node -v). Download from: https://nodejs.org/"
}
Write-Ok "Node.js found: $(node -v)"

if (-not (Get-Command pnpm -ErrorAction SilentlyContinue)) {
    Write-Warn "pnpm not found. Installing..."
    npm install -g pnpm
}
Write-Ok "pnpm found: $(pnpm -v)"

# -- Git hooks -------------------------------------------------------------------

Write-Step "Configuring in-repo git hooks (.githooks/)"
git config core.hooksPath .githooks
if ($LASTEXITCODE -eq 0) {
    Write-Ok "Git hooks path set to .githooks (Prisma migration guard enabled)"
} else {
    Write-Warn "Could not set core.hooksPath. Run 'git config core.hooksPath .githooks' manually from the repo root."
}

# -- Dependencies ----------------------------------------------------------------

Write-Step "Installing dependencies"
pnpm install
Write-Ok "Dependencies installed"

# -- Environment -----------------------------------------------------------------

Write-Step "Setting up environment"

if (-not (Test-Path "apps\web\.env.local")) {
    Copy-Item ".env.example" "apps\web\.env.local"
    # Generate AUTH_SECRET
    $secret = ""
    if (Get-Command python -ErrorAction SilentlyContinue) {
        $secret = python -c "import secrets; print(secrets.token_hex(32))"
    } elseif (Get-Command python3 -ErrorAction SilentlyContinue) {
        $secret = python3 -c "import secrets; print(secrets.token_hex(32))"
    } else {
        $secret = [System.Web.Security.Membership]::GeneratePassword(64, 8)
    }
    if ($secret) {
        (Get-Content "apps\web\.env.local") -replace '<generate with: openssl rand -base64 32>', $secret |
            Set-Content "apps\web\.env.local"
    }
    # Generate CREDENTIAL_ENCRYPTION_KEY
    $encKey = -join ((1..32) | ForEach-Object { "{0:x2}" -f (Get-Random -Maximum 256) })
    (Get-Content "apps\web\.env.local") -replace '<generate with: openssl rand -hex 32>', $encKey |
        Set-Content "apps\web\.env.local"
    # Enable Docker internal URL for Ollama
    Add-Content -Path "apps\web\.env.local" -Value "OLLAMA_INTERNAL_URL=http://ollama:11434"
    Write-Ok "Created apps\web\.env.local with generated secrets"
} else {
    Write-Ok "apps\web\.env.local already exists -- skipping"
}

if (-not (Test-Path "packages\db\.env")) {
    Copy-Item ".env.example" "packages\db\.env"
    Write-Ok "Created packages\db\.env"
}

# Ensure root .env has real secrets for Docker Compose
$rootEnv = ".env"
if (-not (Test-Path $rootEnv)) {
    Copy-Item ".env.docker.example" $rootEnv
    # Generate secrets for Docker Compose env
    $authBytes = New-Object byte[] 32
    [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($authBytes)
    $authSecret = [Convert]::ToBase64String($authBytes)
    $encKey = -join ((1..32) | ForEach-Object { "{0:x2}" -f (Get-Random -Maximum 256) })
    (Get-Content $rootEnv) -replace '<generate with: openssl rand -base64 32>', $authSecret |
        Set-Content $rootEnv
    (Get-Content $rootEnv) -replace '<generate with: openssl rand -hex 32>', $encKey |
        Set-Content $rootEnv
    Write-Ok "Created root .env with generated secrets"
}

# -- Databases -------------------------------------------------------------------

Write-Step "Starting services (PostgreSQL + Neo4j + Ollama)"
docker compose up -d

Write-Host "  Waiting for PostgreSQL to be ready..."
$retries = 30
do {
    $null = docker compose exec -T postgres pg_isready -U dpf -q 2>$null
    if ($LASTEXITCODE -eq 0) { break }
    $retries--
    if ($retries -eq 0) { Write-Fail "PostgreSQL did not start. Check: docker compose logs postgres" }
    Start-Sleep -Seconds 2
} while ($true)
Write-Ok "PostgreSQL is ready"

Write-Host "  Waiting for Ollama... (first run may take a few minutes to download default model)" -ForegroundColor Yellow
$retries = 90
do {
    $null = docker compose exec -T ollama curl -sf http://localhost:11434/api/tags 2>$null
    if ($LASTEXITCODE -eq 0) { break }
    $retries--
    if ($retries -eq 0) {
        Write-Host "  [FAIL] Ollama did not start in time. Check: docker compose logs ollama" -ForegroundColor Red
        exit 1
    }
    Start-Sleep -Seconds 2
} while ($true)
Write-Host "  [OK] Ollama is ready" -ForegroundColor Green

# -- Database Setup --------------------------------------------------------------

Write-Step "Running database migrations"
pnpm db:migrate
Write-Ok "Migrations complete"

Write-Step "Seeding database"
pnpm db:seed
Write-Ok "Database seeded with roles, agents, and default admin user"

# -- Agent rulebook conformance --------------------------------------------------
# Every install must ship the canonical AGENTS.md plus pointer files for each
# supported AI tool. If any are missing or have lost their pointer to AGENTS.md,
# fail the install loudly so the issue is fixed at the seed, not discovered at
# runtime when an agent operates without rules.

Write-Step "Verifying agent rulebook"

$agentRulebook = "AGENTS.md"
if (-not (Test-Path $agentRulebook)) {
    Write-Fail "Canonical agent rulebook missing: $agentRulebook. This install is broken; do not proceed."
}
Write-Ok "Canonical rulebook: $agentRulebook"

$pointers = @(
    "CLAUDE.md",
    ".cursor/rules/000-load-agents.mdc",
    ".clinerules/000-load-agents.md",
    ".github/copilot-instructions.md",
    "CONVENTIONS.md",
    ".continue/rules/000-load-agents.md"
)
foreach ($p in $pointers) {
    if (-not (Test-Path $p)) {
        Write-Fail "Pointer file missing: $p. Re-clone or restore from main."
    }
    if (-not (Select-String -Path $p -Pattern "AGENTS.md" -Quiet)) {
        Write-Fail "Pointer file does not reference AGENTS.md: $p. Drift detected."
    }
}
Write-Ok "Pointer files intact: $($pointers.Count) tools wired to AGENTS.md"

# -- Agent toolchain bootstrap (BI-4B17051B) -------------------------------------
# Converges Claude Code + Codex CLI sessions to a kernel-aware state, seeds
# kernel-tier memory, and persists agentToolchain readiness state.
Write-Step "Converging DPF agent toolchain"
$bootstrapScript = Join-Path (Get-Location).Path "scripts\dpf-bootstrap-agent-toolchain.ps1"
if (Test-Path $bootstrapScript) {
    try {
        & $bootstrapScript -RepoRoot (Get-Location).Path
    } catch {
        Write-Warn "Agent toolchain bootstrap encountered an issue (non-fatal): $_"
    }
} else {
    Write-Warn "Agent toolchain bootstrap script missing at $bootstrapScript"
}

# -- Done ------------------------------------------------------------------------

Write-Host ""
Write-Host "  Setup complete!" -ForegroundColor Green
Write-Host ""
Write-Host "  Start the app:  pnpm dev"
Write-Host "  Open:           http://localhost:3000"
Write-Host ""
Write-Host "  Default login:"
Write-Host "    Email:    admin@dpf.local"
Write-Host "    Password: changeme123"
Write-Host ""
Write-Host "  Change the password before any non-local deployment."
Write-Host ""
