#!/usr/bin/env php
<?php
/**
 * Run pending migrations on the production database.
 *
 * Usage: php app/migrations/run.php [DB_PATH]
 *
 * If no DB_PATH is given, defaults to storage/xamxam.db.
 *
 * Scans both migrations/pending/ and migrations/applied/ for .sql files.
 * Each is applied in alphabetical order if not already tracked in _migrations.
 */

$root = dirname(__DIR__);
$dbPath = $argv[1] ?? ($root . '/storage/xamxam.db');

if (!file_exists($dbPath)) {
    die("Database not found: $dbPath\n");
}

$pdo = new PDO('sqlite:' . $dbPath);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Create migrations tracking table
$pdo->exec("
    CREATE TABLE IF NOT EXISTS _migrations (
        name TEXT PRIMARY KEY,
        applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
");

$applied = $pdo->query("SELECT name FROM _migrations")->fetchAll(PDO::FETCH_COLUMN);

$pendingDir = $root . '/migrations/pending';
$appliedDir = $root . '/migrations/applied';

if (!is_dir($appliedDir)) {
    mkdir($appliedDir, 0755, true);
}

// Collect .sql files from both pending and applied dirs
$files = [];
foreach ([$pendingDir, $appliedDir] as $dir) {
    if (!is_dir($dir)) continue;
    foreach (glob($dir . '/*.sql') as $f) {
        $files[basename($f)] = $f;
    }
}
ksort($files);

if (empty($files)) {
    echo "No pending migration files.\n";
    exit(0);
}

$count = 0;
foreach ($files as $name => $file) {

    if (in_array($name, $applied, true)) {
        echo "Skip (already applied): $name\n";
        continue;
    }

    echo "Applying: $name\n";
    $sql = file_get_contents($file);

    // Split into individual statements to handle partial failures gracefully
    // (e.g. ALTER TABLE may fail with "duplicate column" but DROP VIEW must still run)
    $statements = array_filter(
        array_map('trim', explode(';', $sql)),
        fn($s) => $s !== ''
    );

    $errors = [];
    foreach ($statements as $stmt) {
        try {
            $pdo->exec($stmt . ';');
        } catch (PDOException $e) {
            $msg = $e->getMessage();
            if (stripos($msg, 'duplicate column name') !== false
                || stripos($msg, 'no such column') !== false) {
                echo "  Skipping (already applied): " . substr($stmt, 0, 60) . "...\n";
                continue;
            }
            $errors[] = $msg;
        }
    }

    if (empty($errors)) {
        $pdo->prepare("INSERT OR REPLACE INTO _migrations (name) VALUES (?)")->execute([$name]);
        if (str_starts_with($file, $pendingDir)) {
            rename($file, $appliedDir . '/' . $name);
        }
        $count++;
    } else {
        echo "  FAILED: " . implode(' | ', $errors) . "\n";
        throw new PDOException(implode(' | ', $errors));
    }
}

echo "$count migration(s) applied.\n";
