#!/usr/bin/env php
<?php
/**
 * api-key CLI
 *
 * Gestiona claves de API para integraciones máquina-a-máquina.
 *
 * Uso:
 *   php bin/api-key create --name="Cron sync EST1" --scopes=ingest --estacion=1 --ips=127.0.0.1
 *   php bin/api-key list
 *   php bin/api-key revoke --id=3
 *
 * La clave en claro solo se muestra al crearla. Guárdala en lugar seguro;
 * en BD solo queda el hash SHA-256.
 */

if (php_sapi_name() !== 'cli') {
    fwrite(STDERR, "Este script se ejecuta solo por consola.\n");
    exit(1);
}

$basePath = dirname(__DIR__);
define('BASE_PATH', $basePath . DIRECTORY_SEPARATOR);

require $basePath . '/core/helpers/Env.php';
Env::load($basePath . '/.env');

require $basePath . '/app/config/Config.php';
require $basePath . '/app/config/ConfigEnv.php';

if (class_exists('ConfigEnv') && method_exists('ConfigEnv', 'applyEnvironmentOverrides')) {
    ConfigEnv::applyEnvironmentOverrides();
}

$dbConfig = ConfigEnv::$DB_CONNECTIONS['klee'];
$dsn = "mysql:host={$dbConfig['host']};dbname={$dbConfig['dbname']};charset=utf8mb4";
$pdo = new PDO($dsn, $dbConfig['user'], $dbConfig['password'], array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
));

$command = $argv[1] ?? 'help';
$opts = parseOpts(array_slice($argv, 2));

switch ($command) {
    case 'create':
        cmdCreate($pdo, $opts);
        break;
    case 'list':
        cmdList($pdo);
        break;
    case 'revoke':
        cmdRevoke($pdo, $opts);
        break;
    case 'help':
    default:
        usage();
        exit($command === 'help' ? 0 : 1);
}

function usage()
{
    echo "Uso:\n";
    echo "  php bin/api-key create --name=\"...\" [--scopes=ingest] [--estacion=1] [--ips=ip1,ip2/24] [--rate=120] [--expira=YYYY-MM-DD]\n";
    echo "  php bin/api-key list\n";
    echo "  php bin/api-key revoke --id=N\n";
}

function parseOpts(array $args)
{
    $opts = array();
    foreach ($args as $arg) {
        if (preg_match('/^--([a-zA-Z0-9_]+)=(.*)$/', $arg, $m)) {
            $opts[$m[1]] = $m[2];
        } elseif (preg_match('/^--([a-zA-Z0-9_]+)$/', $arg, $m)) {
            $opts[$m[1]] = true;
        }
    }
    return $opts;
}

function cmdCreate($pdo, $opts)
{
    if (empty($opts['name'])) {
        fwrite(STDERR, "Error: --name es obligatorio\n");
        exit(1);
    }

    $prefix = strtolower(bin2hex(random_bytes(4)));
    $secret = bin2hex(random_bytes(20));
    $plainKey = 'klee_' . $prefix . '_' . $secret;
    $hash = hash('sha256', $plainKey);

    $stmt = $pdo->prepare(
        "INSERT INTO api_keys (TenantId, Nombre, KeyPrefix, KeyHash, Scopes, AllowedIps, IdEstacion,"
        . " RateLimitPorMinuto, Estado, FechaExpiracion, FechaRegistro)"
        . " VALUES (:TenantId, :Nombre, :KeyPrefix, :KeyHash, :Scopes, :AllowedIps, :IdEstacion,"
        . " :Rate, 1, :Expira, :FechaRegistro)"
    );

    $stmt->execute(array(
        ':TenantId'   => isset($opts['tenant']) ? (int)$opts['tenant'] : null,
        ':Nombre'     => $opts['name'],
        ':KeyPrefix'  => $prefix,
        ':KeyHash'    => $hash,
        ':Scopes'     => isset($opts['scopes']) ? $opts['scopes'] : 'ingest',
        ':AllowedIps' => isset($opts['ips']) ? $opts['ips'] : null,
        ':IdEstacion' => isset($opts['estacion']) ? (int)$opts['estacion'] : null,
        ':Rate'       => isset($opts['rate']) ? (int)$opts['rate'] : 120,
        ':Expira'     => isset($opts['expira']) ? $opts['expira'] : null,
        ':FechaRegistro' => date('Y-m-d H:i:s'),
    ));

    $id = (int)$pdo->lastInsertId();

    echo "\n";
    echo "API key creada (Id={$id}, prefix={$prefix})\n";
    echo "GUÁRDALA AHORA — no se volverá a mostrar:\n\n";
    echo "  {$plainKey}\n\n";
    echo "Uso en HTTP:\n";
    echo "  curl -H \"X-Api-Key: {$plainKey}\" -H \"Content-Type: application/json\" -d @batch.json \\\n";
    echo "       \"http://tu-host/?c=api&a=ingest\"\n\n";
}

function cmdList($pdo)
{
    $rows = $pdo->query(
        "SELECT Id, Nombre, KeyPrefix, Scopes, IdEstacion, Estado, UltimoUso, FechaExpiracion, FechaRegistro"
        . " FROM api_keys ORDER BY Id DESC"
    )->fetchAll(PDO::FETCH_ASSOC);

    if (empty($rows)) {
        echo "(no hay claves)\n";
        return;
    }

    printf("%-4s %-30s %-10s %-15s %-8s %-7s %-19s %-19s\n",
        'Id', 'Nombre', 'Prefix', 'Scopes', 'Estacion', 'Estado', 'UltimoUso', 'Expira');
    echo str_repeat('-', 120) . "\n";
    foreach ($rows as $r) {
        printf("%-4s %-30s %-10s %-15s %-8s %-7s %-19s %-19s\n",
            $r['Id'],
            mb_substr((string)$r['Nombre'], 0, 30),
            $r['KeyPrefix'],
            mb_substr((string)$r['Scopes'], 0, 15),
            $r['IdEstacion'] ?? '-',
            $r['Estado'] ? 'activa' : 'revoc.',
            $r['UltimoUso'] ?? '-',
            $r['FechaExpiracion'] ?? '-'
        );
    }
}

function cmdRevoke($pdo, $opts)
{
    if (empty($opts['id'])) {
        fwrite(STDERR, "Error: --id es obligatorio\n");
        exit(1);
    }
    $id = (int)$opts['id'];
    $stmt = $pdo->prepare("UPDATE api_keys SET Estado = 0, FechaModificacion = :ahora WHERE Id = :Id");
    $stmt->execute(array(':ahora' => date('Y-m-d H:i:s'), ':Id' => $id));
    echo "API key {$id} revocada\n";
}
