<?php
declare(strict_types=1);
date_default_timezone_set('UTC');
require dirname(__DIR__) . '/php/Database.php';
use Aen\Database;
function output(mixed $value): void { echo json_encode($value, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR) . PHP_EOL; }
try {
    $root = dirname(__DIR__);
    $storage = $root . '/runtime';
    $command = $argv[1] ?? 'help';
    if ($command === 'help') {
        echo "PHP PDO SQLite workshop (private runtime directory)\n";
        echo "php tools/console.php init|info|contacts|report [paid|new|cancelled] [minimum-rubles]\n";
        echo "php tools/console.php join [LEFT|INNER]|aggregate [status] [minimum-count]\n";
        echo "php tools/console.php reserve [1..100] [--fail]|import [local-json-file]\n";
        echo "php tools/console.php index [on|off]|check|backup|export-json\n";
        exit(0);
    }
    $known = ['init','info','contacts','report','join','aggregate','reserve','import','index','check','backup','export-json'];
    if (!in_array($command, $known, true)) throw new RuntimeException('Unknown command. Use help.');
    if ($command === 'init' && !is_dir($storage) && !mkdir($storage, 0700, true)) throw new RuntimeException('Cannot create private storage.');
    $db = new Database($storage . '/app.sqlite', $command === 'init');
    switch ($command) {
        case 'init': output(['created' => 'runtime/app.sqlite', 'sqlite' => $db->version(), 'counts' => $db->counts(), 'settings' => $db->settings()]); break;
        case 'info': output(['sqlite' => $db->version(), 'counts' => $db->counts(), 'settings' => $db->settings()]); break;
        case 'contacts': output($db->contacts()); break;
        case 'report': output($db->filter($argv[2] ?? 'paid', $argv[3] ?? '10000')); break;
        case 'join': output($db->joined($argv[2] ?? 'LEFT')); break;
        case 'aggregate': output($db->aggregate($argv[2] ?? 'paid', $argv[3] ?? '1')); break;
        case 'reserve': $db->reserve($argv[2] ?? '10', ($argv[3] ?? '') === '--fail'); output(['stock' => $db->counts()['stock'], 'reservations' => $db->ledger()]); break;
        case 'import':
            $path = $argv[2] ?? $root . '/fixtures/contacts-import.json';
            if (!is_file($path) || filesize($path) > 480000) throw new RuntimeException('Expected a local JSON file up to 480000 bytes.');
            output(['imported' => $db->import(file_get_contents($path)), 'contacts' => $db->counts()['contacts']]); break;
        case 'index':
            $state = $argv[2] ?? 'on'; if (!in_array($state, ['on', 'off'], true)) throw new RuntimeException('Index: on or off.');
            $db->index($state === 'on'); output($db->explain()); break;
        case 'check': output($db->integrity()); break;
        case 'backup':
            $directory = $storage . '/backups'; if (!is_dir($directory) && !mkdir($directory, 0700)) throw new RuntimeException('Cannot create backup directory.');
            $name = 'app-' . gmdate('Ymd-His') . '-' . bin2hex(random_bytes(3)) . '.sqlite';
            $db->backup($directory . '/' . $name); output(['backup' => 'runtime/backups/' . $name, 'method' => 'VACUUM INTO']); break;
        case 'export-json': output($db->exportContacts()); break;
    }
} catch (Throwable $error) {
    fwrite(STDERR, 'Error: ' . $error->getMessage() . PHP_EOL);
    exit(1);
}
