#!/usr/bin/env php
<?php
declare(strict_types=1);
ini_set('serialize_precision', '-1');
require dirname(__DIR__).'/vendor/autoload.php';
use Icom\Application;
use Icom\Config;
use Icom\Database\{Database, Migrator};
use Icom\Http\Response;
use Nyholm\Psr7\ServerRequest;
$root = dirname(__DIR__);
$command = $argv[1] ?? 'help';
try {
    switch ($command) {
        case 'help':
        case '--help':
            echo "ICOM Framework ".Application::VERSION." (developer preview)\n\n";
            echo "  about                  Runtime and release information\n  key:generate           Set an empty APP_KEY without printing it\n  routes                 List registered application routes\n  make:controller Name   Create a controller; never overwrite\n  migrate                Apply pending database migrations\n  cache:clear            Clear application cache records\n  test                   Run the regression suite\n  benchmark [iterations] In-memory kernel microbenchmark\n";
            break;
        case 'about':
            echo json_encode(['framework' => 'ICOM', 'version' => Application::VERSION, 'php' => PHP_VERSION, 'sapi' => PHP_SAPI, 'preview' => true], JSON_PRETTY_PRINT)."\n";
            break;
        case 'key:generate':
            $file = $root.'/.env';
            $content = is_file($file) ? file_get_contents($file) : file_get_contents($root.'/.env.example');
            if (preg_match('/^APP_KEY=(.+)$/m', $content)) throw new RuntimeException('APP_KEY already exists. Key rotation requires a planned migration.');
            $line = 'APP_KEY='.base64_encode(random_bytes(32));
            $content = preg_match('/^APP_KEY=/m', $content) ? preg_replace('/^APP_KEY=.*$/m', $line, $content) : $content."\n".$line."\n";
            $temp = tempnam($root, '.env-');
            if ($temp === false) throw new RuntimeException('Cannot create configuration.');
            try {
                chmod($temp, 0600);
                if (file_put_contents($temp, $content) !== strlen($content) || !rename($temp, $file)) throw new RuntimeException('Cannot save configuration.');
            } finally { if (is_file($temp)) unlink($temp); }
            echo "Application key generated in .env (value not displayed).\n";
            break;
        case 'routes':
            $app = require $root.'/bootstrap.php';
            foreach ($app->router->all() as $route) printf("%-7s %-32s %s\n", $route->method, $route->path, $route->routeName ?? '');
            break;
        case 'make:controller':
            $name = $argv[2] ?? '';
            if (!preg_match('/^[A-Z][A-Za-z0-9]*Controller$/D', $name)) throw new InvalidArgumentException('Use a class name such as ExampleController.');
            $file = fopen($root.'/app/'.$name.'.php', 'x');
            if (!$file) throw new RuntimeException('Controller exists or destination is unavailable.');
            $code = "<?php\ndeclare(strict_types=1);\nnamespace App;\nuse Icom\\Http\\Response;\nuse Psr\\Http\\Message\\ResponseInterface;\nfinal class $name\n{\n    public function __invoke(): ResponseInterface\n    { return Response::json(['message' => 'Hello from $name']); }\n}\n";
            try { if (fwrite($file, $code) !== strlen($code)) throw new RuntimeException('Controller write failed.'); }
            finally { fclose($file); }
            echo "Created app/$name.php. Register it in routes/web.php.\n";
            break;
        case 'migrate':
            $app = require $root.'/bootstrap.php';
            $scope = $app->container->scope();
            try {
                $migrator = new Migrator($scope->get(Database::class), $root.'/migrations', $root.'/storage/migrations.lock');
                $ran = $migrator->run();
                echo $ran === [] ? "No pending migrations.\n" : implode("\n", $ran)."\n";
            } finally { $scope->clear(); }
            break;
        case 'cache:clear':
            $app = require $root.'/bootstrap.php';
            if (!$app->container->get(\Psr\SimpleCache\CacheInterface::class)->clear()) throw new RuntimeException('Some cache records could not be cleared.');
            echo "Cache records cleared. Rate-limit locks were preserved.\n";
            break;
        case 'test':
            require $root.'/tests/run.php';
            break;
        case 'benchmark':
            $iterations = filter_var($argv[2] ?? '10000', FILTER_VALIDATE_INT);
            if ($iterations === false || $iterations < 100 || $iterations > 100000) throw new InvalidArgumentException('Iterations must be 100–100000.');
            $app = new Application();
            $app->get('/hello/{name}', static fn (string $name) => Response::json(['hello' => $name]));
            $request = new ServerRequest('GET', 'http://localhost/hello/Developer');
            for ($i = 0; $i < 1000; $i++) $app->handle($request);
            $samples = []; $start = hrtime(true);
            for ($i = 0; $i < $iterations; $i++) {
                $t = hrtime(true); $app->handle($request); $samples[] = (hrtime(true) - $t) / 1000;
            }
            $seconds = (hrtime(true) - $start) / 1e9; sort($samples);
            echo json_encode(['workload' => 'In-memory GET /hello/{name}; no network, DB or production middleware', 'php' => PHP_VERSION, 'sapi' => PHP_SAPI, 'os' => PHP_OS_FAMILY, 'opcache_cli' => ini_get('opcache.enable_cli'), 'concurrency' => 1, 'warmup' => 1000, 'iterations' => $iterations, 'elapsed_seconds' => round($seconds, 6), 'dispatches_per_second' => round($iterations / $seconds), 'p50_us' => round($samples[(int)floor(($iterations - 1) * .5)], 3), 'p95_us' => round($samples[(int)floor(($iterations - 1) * .95)], 3), 'p99_us' => round($samples[(int)floor(($iterations - 1) * .99)], 3), 'peak_php_bytes' => memory_get_peak_usage(true), 'comparative_claim' => false], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)."\n";
            break;
        default: throw new InvalidArgumentException('Unknown command. Run php bin/icom help.');
    }
} catch (Throwable $e) { fwrite(STDERR, 'Error: '.$e->getMessage()."\n"); exit(1); }
