<?php
/**
 * SQL 结构迁移执行器（轻量版）
 *
 * 目标：让数据库结构变更以 "V{n}__xxx.sql" 脚本形式沉淀（仅结构，不推业务数据）。
 * 使用：php scripts/sql_migrate.php
 *
 * 约定：
 * - 脚本目录：database/migrations
 * - 脚本命名：V1__xxx.sql, V2__xxx.sql ...（按数字升序执行）
 * - 记录表：schema_sql_migrations（记录已执行版本）
 */

$baseDir = realpath(__DIR__ . '/../database/migrations');
if ($baseDir === false) {
    fwrite(STDERR, "SQL migrations dir not found.\n");
    exit(1);
}

// 读取 .env（尽量少依赖 Laravel 容器，便于 CI/部署直接跑）
$envPath = realpath(__DIR__ . '/../.env');
$env = [];
if ($envPath && file_exists($envPath)) {
    foreach (file($envPath, FILE_IGNORE_NEW_LINES) as $line) {
        $line = trim($line);
        if ($line === '' || str_starts_with($line, '#')) {
            continue;
        }
        if (!str_contains($line, '=')) {
            continue;
        }
        [$k, $v] = explode('=', $line, 2);
        $k = trim($k);
        $v = trim($v);
        $v = trim($v, "\"'");
        $env[$k] = $v;
    }
}

// env 变量优先级：系统环境变量 > .env
$getEnv = function (string $key, string $default = '') use ($env): string {
    $v = getenv($key);
    if ($v !== false && $v !== '') {
        return (string) $v;
    }
    return (string) ($env[$key] ?? $default);
};

$driver = $getEnv('DB_CONNECTION', 'mysql');
$host = $getEnv('DB_HOST', '127.0.0.1');
$port = $getEnv('DB_PORT', $driver === 'pgsql' ? '5432' : ($driver === 'sqlite' ? '' : '3306'));
$db   = $getEnv('DB_DATABASE', '');
$user = $getEnv('DB_USERNAME', '');
$pass = $getEnv('DB_PASSWORD', '');

if ($driver === 'sqlite') {
    // sqlite: DB_DATABASE 可能是绝对路径
    $dsn = $db !== '' ? "sqlite:" . $db : 'sqlite::memory:';
} elseif ($driver === 'pgsql') {
    $dsn = "pgsql:host={$host};port={$port};dbname={$db}";
} else {
    // mysql
    $charset = $getEnv('DB_CHARSET', 'utf8mb4');
    $dsn = "mysql:host={$host};port={$port};dbname={$db};charset={$charset}";
}

try {
    $pdo = new PDO($dsn, $user, $pass, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]);
} catch (Throwable $e) {
    fwrite(STDERR, "DB connect failed: {$e->getMessage()}\n");
    exit(2);
}

// 确保迁移记录表存在
// applied_at 使用 TEXT，确保 sqlite/mysql 下都可用（避免 DATETIME 在部分方言下不兼容）
$pdo->exec("CREATE TABLE IF NOT EXISTS schema_sql_migrations (\n  version VARCHAR(50) PRIMARY KEY,\n  description VARCHAR(255) NULL,\n  applied_at TEXT NOT NULL\n)");

$applied = [];
foreach ($pdo->query('SELECT version FROM schema_sql_migrations') as $row) {
    $applied[(string) $row['version']] = true;
}

$files = glob($baseDir . '/V*__*.sql');
sort($files);

$pending = [];
foreach ($files as $file) {
    $name = basename($file);
    if (!preg_match('/^(V\d+)__.+\.sql$/', $name, $m)) {
        continue;
    }
    $version = $m[1];
    if (isset($applied[$version])) {
        continue;
    }
    $pending[] = ['version' => $version, 'file' => $file, 'name' => $name];
}

if (count($pending) === 0) {
    fwrite(STDOUT, "No pending SQL migrations.\n");
    exit(0);
}

foreach ($pending as $item) {
    $sql = file_get_contents($item['file']);
    $sql = $sql === false ? '' : $sql;

    fwrite(STDOUT, "Applying {$item['name']} ...\n");

    $pdo->beginTransaction();
    try {
        // 简单处理：按分号执行（对于包含存储过程等复杂语法的脚本，需拆分策略升级）
        $statements = array_filter(array_map('trim', preg_split('/;\s*\n/', $sql)));
        foreach ($statements as $stmt) {
            if ($stmt === '' || str_starts_with(ltrim($stmt), '--')) {
                continue;
            }
            $pdo->exec($stmt);
        }

        $desc = preg_replace('/^V\d+__/', '', $item['name']);
        $desc = preg_replace('/\.sql$/', '', $desc);

        $stmt = $pdo->prepare('INSERT INTO schema_sql_migrations(version, description, applied_at) VALUES(?, ?, ?)');
        $stmt->execute([$item['version'], $desc, date('Y-m-d H:i:s')]);

        $pdo->commit();
    } catch (Throwable $e) {
        $pdo->rollBack();
        fwrite(STDERR, "Failed {$item['name']}: {$e->getMessage()}\n");
        exit(3);
    }
}

fwrite(STDOUT, "SQL migrations applied: " . count($pending) . "\n");
