#!/usr/bin/env php
<?php
declare(strict_types=1);

/**
 * Celena CMS — CLI: миграции, кеш, плагины.
 *   php bin/celena migrate
 *   php bin/celena cache:clear
 *   php bin/celena route:list
 */

if (PHP_SAPI !== 'cli') {
    fwrite(STDERR, "CLI only.\n");
    exit(1);
}

$root = dirname(__DIR__);
require $root . '/core/Autoloader.php';
\Celena\Core\Autoloader::register($root);

$kernel = (new \Celena\Core\Kernel($root))->boot();
$container = \Celena\Core\Kernel::container();

$cmd = $argv[1] ?? 'help';
$args = array_slice($argv, 2);

try {
    switch ($cmd) {
        case 'install':
            // Установка из консоли:
            //   php bin/celena install --db=mysql --db-host=127.0.0.1 --db-name=celena \
            //     --db-user=root --db-pass=secret --admin-email=admin@example.com --admin-pass=secret123
            if (is_file($root . '/install.lock')) {
                fwrite(STDERR, "CMS уже установлена (install.lock). Удалите файл для переустановки.\n");
                exit(1);
            }
            $opt = [];
            foreach ($args as $a) {
                if (preg_match('/^--([a-z-]+)=(.*)$/s', $a, $m)) $opt[$m[1]] = $m[2];
            }
            $required = ['db-name', 'db-user', 'admin-email', 'admin-pass'];
            $missing = array_diff($required, array_keys($opt));
            if ($missing !== []) {
                fwrite(STDERR, "Не хватает параметров: --" . implode(', --', $missing) . "\n");
                fwrite(STDERR, "Пример: php bin/celena install --db=mysql --db-name=celena --db-user=root --db-pass=... --admin-email=admin@site.com --admin-pass=...\n");
                exit(1);
            }
            $setup = new \Celena\Core\Install\SetupService($root);
            foreach ($setup->checkEnvironment() as $c) {
                $mark = $c['ok'] ? 'ok' : ($c['required'] ? 'FAIL' : 'warn');
                printf("  [%-4s] %s — %s\n", $mark, $c['label'], $c['details']);
            }
            if (!$setup->environmentOk()) {
                fwrite(STDERR, "Окружение не готово — исправьте пункты FAIL.\n");
                exit(1);
            }
            $db = $setup->normalizeDb([
                'driver' => $opt['db'] ?? 'mysql',
                'host'   => $opt['db-host'] ?? '127.0.0.1',
                'port'   => $opt['db-port'] ?? '',
                'name'   => $opt['db-name'],
                'user'   => $opt['db-user'],
                'pass'   => $opt['db-pass'] ?? '',
                'prefix' => $opt['db-prefix'] ?? 'cl_',
            ]);
            $log = $setup->install(
                $db,
                ['url' => $opt['url'] ?? 'http://localhost', 'name' => $opt['site-name'] ?? 'Celena CMS'],
                ['email' => $opt['admin-email'], 'password' => $opt['admin-pass'], 'name' => $opt['admin-name'] ?? 'Администратор'],
            );
            foreach ($log as $line) echo "  ✓ $line\n";
            if (is_file($root . '/install.php')) {
                echo @unlink($root . '/install.php')
                    ? "  ✓ install.php удалён\n"
                    : "  ! Удалите install.php вручную\n";
            }
            echo "Готово. Вход в админку: /admin/login\n";
            break;

        case 'migrate':
            $conn = $container->make(\Celena\Core\Database\Connection::class);
            $logger = $container->make(\Celena\Core\Logger::class);
            $runner = new \Celena\Core\Database\MigrationRunner($conn, $logger);
            $ran = $runner->run($root . '/core/Database/migrations');
            $totalRan = count($ran);
            foreach ($ran as $m) echo "  [core] ✓ $m\n";
            // Прогон миграций каждого активного плагина (идемпотентно — учётная таблица в самом MigrationRunner).
            foreach (glob($root . '/plugins/*/migrations', GLOB_ONLYDIR) ?: [] as $dir) {
                $pluginSlug = basename(dirname($dir));
                $pluginRunner = new \Celena\Core\Database\MigrationRunner($conn, $logger);
                $pluginRan = $pluginRunner->run($dir);
                foreach ($pluginRan as $m) echo "  [$pluginSlug] ✓ $m\n";
                $totalRan += count($pluginRan);
            }
            if ($totalRan === 0) {
                echo "Nothing to migrate.\n";
            } else {
                echo "$totalRan migration(s) applied.\n";
            }
            break;

        case 'queue:work':
            require $root . '/core/bootstrap.php';
            $max = 50;
            foreach ($args as $a) {
                if (preg_match('/^--max=(\d+)s?$/', $a, $m)) $max = (int) $m[1];
            }
            $qm = new \Celena\Core\Queue\QueueManager(
                $container->make(\Celena\Core\Database\Connection::class),
                $container->make(\Celena\Core\Logger::class),
                $container,
            );
            $n = $qm->work($max);
            echo "Processed: $n job(s).\n";
            break;

        case 'media:fix-dimensions':
            require $root . '/core/bootstrap.php';
            $conn = $container->make(\Celena\Core\Database\Connection::class);
            $rows = $conn->builder('celena_media')->whereNull('width')->get();
            $fixed = 0;
            foreach ($rows as $r) {
                $path = (string) $r['path'];
                if (!is_file($path)) continue;
                $info = @getimagesize($path);
                if ($info === false) continue;
                $conn->builder('celena_media')->where('id', '=', (int) $r['id'])->update([
                    'width' => $info[0], 'height' => $info[1],
                ]);
                $fixed++;
            }
            echo "Fixed dimensions for $fixed file(s).\n";
            break;

        case 'cache:clear':
            $count = 0;
            foreach (glob($root . '/storage/cache/tpl/*.php') ?: [] as $f) { @unlink($f); $count++; }
            foreach (glob($root . '/storage/cache/data/*') ?: [] as $f)   { @unlink($f); $count++; }
            foreach (glob($root . '/storage/cache/http/*') ?: [] as $f)   { @unlink($f); $count++; }
            echo "Cleared $count cache file(s).\n";
            break;

        case 'route:list':
            // Нужно загрузить bootstrap, чтобы зарегистрировались маршруты.
            require $root . '/core/bootstrap.php';
            // Простой список — инспектируем приватное поле через рефлексию.
            $router = $container->make(\Celena\Core\Http\Router::class);
            $ref = new ReflectionClass($router);
            $prop = $ref->getProperty('routes');
            $prop->setAccessible(true);
            $routes = $prop->getValue($router);
            foreach ($routes as $r) {
                printf("  %-6s %-40s\n", $r['method'], $r['pattern']);
            }
            break;

        case 'mp:keygen':
            // Генерация пары ключей Ed25519 для подписи пакетов маркетплейса.
            $kp = \Celena\Core\Plugin\PackageSigner::keypair();
            echo "Ed25519 keypair для подписи пакетов маркетплейса.\n\n";
            echo "На РЕЕСТРЕ (marketplace.celena.io) — приватный ключ, держать в секрете:\n";
            echo "  MARKETPLACE_SIGN_SECRET=\"{$kp['secret']}\"\n\n";
            echo "На КЛИЕНТАХ (каждый сайт Celena) — публичный ключ:\n";
            echo "  MARKETPLACE_PUBKEY=\"{$kp['public']}\"\n\n";
            echo "Добавьте строки в соответствующие .env. Старые версии без подписи\n";
            echo "не пройдут проверку — переподпишите их (перезалейте) после включения.\n";
            break;

        case 'help':
        default:
            echo "Celena CMS CLI\n\n";
            echo "Usage: php bin/celena <command>\n\n";
            echo "Commands:\n";
            echo "  install         Install the CMS (see: install --help in README)\n";
            echo "  migrate         Run pending migrations\n";
            echo "  cache:clear     Clear template/data/http caches\n";
            echo "  route:list      Show registered routes\n";
            echo "  mp:keygen       Generate Ed25519 keypair for marketplace package signing\n";
            echo "  help            Show this message\n";
    }
} catch (\Throwable $e) {
    fwrite(STDERR, "ERROR: " . $e->getMessage() . "\n");
    fwrite(STDERR, $e->getFile() . ':' . $e->getLine() . "\n");
    exit(1);
}
