<?php

declare(strict_types=1);

/*
 * eduVPN - End-user friendly VPN.
 *
 * Copyright: 2014-2023, The Commons Conservancy eduVPN Programme
 * SPDX-License-Identifier: AGPL-3.0+
 */

require_once dirname(__DIR__) . '/vendor/autoload.php';
$baseDir = dirname(__DIR__);

use Vpn\Portal\Cfg\Config;
use Vpn\Portal\Migration;
use Vpn\Portal\Storage;

try {
    $doInit = false;
    $schemaVersion = null;
    $doMigrate = false;
    $migrateTo = null;
    $dbDsn = null;
    $dbUser = null;
    $dbPass = null;
    $setJournalMode = null;
    for ($i = 1; $i < $argc; ++$i) {
        if ('--init' === $argv[$i]) {
            $doInit = true;

            continue;
        }

        if ('--version' === $argv[$i]) {
            if ($i + 1 < $argc) {
                $schemaVersion = $argv[$i + 1];
            }

            continue;
        }

        if ('--migrate' === $argv[$i]) {
            $doMigrate = true;

            continue;
        }

        if ('--dsn' === $argv[$i]) {
            if ($i + 1 < $argc) {
                $dbDsn = $argv[$i + 1];
            }

            continue;
        }

        if ('--user' === $argv[$i]) {
            if ($i + 1 < $argc) {
                $dbUser = $argv[$i + 1];
            }

            continue;
        }

        if ('--pass' === $argv[$i]) {
            if ($i + 1 < $argc) {
                $dbPass = $argv[$i + 1];
            }

            continue;
        }

        if ('--set-journal-mode' === $argv[$i]) {
            if ($i + 1 < $argc) {
                $setJournalMode = $argv[$i + 1];
                if (!in_array($setJournalMode, ['delete', 'wal'], true)) {
                    throw new Exception(sprintf('journal mode "%s" not supported', $setJournalMode));
                }
            }

            continue;
        }

        if ('--help' === $argv[$i]) {
            echo 'SYNTAX: ' . $argv[0] . ' [--init] [--version VERSION] [--migrate] [--set-journal-mode JOURNAL_MODE] [--dsn DSN] [--user USER] [--pass PASS]' . \PHP_EOL;

            exit(0);
        }
    }

    $config = Config::fromFile($baseDir . '/config/config.php');
    $dbConfig = $config->dbConfig($baseDir);
    $db = new PDO(
        $dbDsn ?? $dbConfig->dbDsn(),
        $dbUser ?? $dbConfig->dbUser(),
        $dbPass ?? $dbConfig->dbPass(),
        $dbConfig->dbOptions()
    );
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $driverName = $db->getAttribute(PDO::ATTR_DRIVER_NAME);
    if (!$doInit && !$doMigrate) {
        echo 'Database Driver        : ' . $driverName . PHP_EOL;
        if ('sqlite' === $driverName) {
            $queryResult = $db->query('PRAGMA journal_mode');
            $currentJournalMode = $queryResult->fetchColumn();
            $queryResult->closeCursor();
            if (null !== $setJournalMode) {
                if ($currentJournalMode !== $setJournalMode) {
                    $queryResult = $db->query(sprintf('PRAGMA journal_mode = %s', $setJournalMode));
                    if ($setJournalMode !== $currentJournalMode = $queryResult->fetchColumn()) {
                        throw new Exception(sprintf('unable to set "%s" journal mode', $setJournalMode));
                    }
                }
            }
            echo 'Journal Mode           : ' . $currentJournalMode . PHP_EOL;
        }

        // show database status information
        $currentVersion = Migration::getCurrentVersion($db);
        $latestVersion = Storage::CURRENT_SCHEMA_VERSION;
        echo 'Current Schema Version : ' . ($currentVersion ?? 'N/A') . PHP_EOL;
        echo 'Latest Schema Version  : ' . $latestVersion . PHP_EOL;

        if ($currentVersion === $latestVersion) {
            echo 'Status                 : **OK**' . PHP_EOL;

            exit(0);
        }
        if (null === $currentVersion) {
            echo 'Status                 : **Initialization Required** (use --init)' . PHP_EOL;

            exit(1);
        }

        echo 'Status                 : **Migration Required** (use --migrate)' . PHP_EOL;

        exit(1);
    }

    Migration::run(
        $db,
        $dbConfig->schemaDir(),
        $schemaVersion ?? Storage::CURRENT_SCHEMA_VERSION,
        $doInit,
        $doMigrate
    );
} catch (Throwable $e) {
    echo 'ERROR: ' . $e->getMessage() . \PHP_EOL;

    exit(1);
}
