<?php
/**
 * lib/vpn.php — Servidores VPN (OpenVPN): esquema autoprovisto + parser de .ovpn.
 *
 * Compartido por el admin (vpn.php) y el endpoint de la app (api/device/vpn.php).
 * Mantiene el DDL en UN solo lugar y lo crea al vuelo (IF NOT EXISTS), así funciona
 * también sobre una DB de producción ya instalada sin re-correr install.php.
 */

declare(strict_types=1);

/** Crea la tabla vpn_servers si falta. Idempotente. */
function ensure_vpn_schema(PDO $pdo): void
{
    $pdo->exec(
        'CREATE TABLE IF NOT EXISTS vpn_servers (
            id            INTEGER PRIMARY KEY AUTOINCREMENT,
            name          TEXT    NOT NULL,
            country       TEXT    NOT NULL DEFAULT \'\',
            flag          TEXT    NOT NULL DEFAULT \'\',
            host          TEXT    NOT NULL DEFAULT \'\',
            protocol      TEXT    NOT NULL DEFAULT \'udp\',
            ovpn          TEXT    NOT NULL,
            requires_auth INTEGER NOT NULL DEFAULT 0,
            username      TEXT    NOT NULL DEFAULT \'\',
            password      TEXT    NOT NULL DEFAULT \'\',
            enabled       INTEGER NOT NULL DEFAULT 1,
            created_at    TEXT    NOT NULL
        )'
    );
}

/**
 * Autodetecta datos de una config OpenVPN (.ovpn).
 *
 * @return array{host:string,port:string,protocol:string,requires_auth:int,name:string}
 */
function vpn_parse_ovpn(string $ovpn): array
{
    $host = '';
    $port = '';
    $proto = '';
    $requiresAuth = 0;

    foreach (preg_split('/\r\n|\r|\n/', $ovpn) ?: [] as $rawLine) {
        $line = trim($rawLine);
        if ($line === '' || $line[0] === '#' || $line[0] === ';') {
            continue;
        }
        $parts = preg_split('/\s+/', $line) ?: [];
        $key = strtolower($parts[0] ?? '');

        if ($key === 'remote' && $host === '') {
            $host = $parts[1] ?? '';
            $port = $parts[2] ?? '';
            // 4º token opcional: udp/tcp.
            if (isset($parts[3]) && $proto === '') {
                $proto = strtolower($parts[3]);
            }
        } elseif ($key === 'proto') {
            // 'proto' explícito gana sobre el token del remote.
            $proto = strtolower($parts[1] ?? '');
        } elseif ($key === 'auth-user-pass') {
            // Sin archivo inline (sólo la directiva) => la app debe pedir user/clave.
            if (!isset($parts[1]) || trim($parts[1]) === '') {
                $requiresAuth = 1;
            }
        }
    }

    // Normaliza protocolo a udp/tcp (proto puede venir 'tcp-client', 'udp4', etc.).
    $proto = str_starts_with($proto, 'tcp') ? 'tcp' : 'udp';

    // Nombre sugerido: el host sin puerto, o vacío.
    $name = $host !== '' ? $host : '';

    return [
        'host'          => $host,
        'port'          => $port,
        'protocol'      => $proto,
        'requires_auth' => $requiresAuth,
        'name'          => $name,
    ];
}
