<?php
/**
 * Validador del sistema — SOLO PARA DIAGNÓSTICO
 * Acceso: https://tucontrato.online/public/check.php?key=CHECK2024
 * BORRAR después de confirmar que todo funciona
 */
if (($_GET['key'] ?? '') !== 'CHECK2024') {
    http_response_code(404);
    die();
}

error_reporting(E_ALL);
ini_set('display_errors', '1');

$checks = [];
$hasError = false;

function ok(string $label, string $detail = ''): array {
    return ['status' => 'ok', 'label' => $label, 'detail' => $detail];
}
function fail(string $label, string $detail = ''): array {
    global $hasError;
    $hasError = true;
    return ['status' => 'fail', 'label' => $label, 'detail' => $detail];
}
function warn(string $label, string $detail = ''): array {
    return ['status' => 'warn', 'label' => $label, 'detail' => $detail];
}

// ── 1. PHP ───────────────────────────────────────────────────────────────────
$checks['PHP'] = version_compare(PHP_VERSION, '8.1.0', '>=')
    ? ok('PHP ' . PHP_VERSION)
    : fail('PHP ' . PHP_VERSION, 'Se requiere 8.1+');

foreach (['pdo', 'pdo_mysql', 'openssl', 'mbstring', 'gd', 'json', 'fileinfo'] as $ext) {
    $checks["ext_$ext"] = extension_loaded($ext)
        ? ok("Extensión $ext")
        : fail("Extensión $ext", 'No disponible');
}

// ── 2. Entorno ───────────────────────────────────────────────────────────────
$rootPath = dirname(__DIR__);
$checks['vendor'] = file_exists($rootPath . '/vendor/autoload.php')
    ? ok('vendor/autoload.php')
    : fail('vendor/autoload.php', 'Ejecutar: composer install');

$checks['env_file'] = file_exists($rootPath . '/.env')
    ? ok('.env encontrado')
    : fail('.env', 'No existe en ' . $rootPath);

try {
    require_once $rootPath . '/vendor/autoload.php';
    $dotenv = Dotenv\Dotenv::createImmutable($rootPath);
    $dotenv->load();
    $checks['dotenv'] = ok('.env cargado correctamente');
} catch (\Throwable $e) {
    $checks['dotenv'] = fail('.env no se pudo cargar', $e->getMessage());
}

// ── 3. Variables de entorno ──────────────────────────────────────────────────
$appUrl   = $_ENV['APP_URL']   ?? null;
$appEnv   = $_ENV['APP_ENV']   ?? null;
$dbName   = $_ENV['DB_NAME']   ?? null;

$checks['APP_URL'] = $appUrl
    ? ok('APP_URL = ' . $appUrl)
    : fail('APP_URL no definida');

$checks['APP_ENV'] = $appEnv
    ? ok('APP_ENV = ' . $appEnv)
    : fail('APP_ENV no definida');

$realProto = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$realUrl   = $realProto . '://' . $_SERVER['HTTP_HOST'];
$checks['url_match'] = (rtrim($appUrl ?? '', '/') === $realUrl)
    ? ok('APP_URL coincide con URL real')
    : fail('APP_URL no coincide', "APP_URL='$appUrl' pero URL real='$realUrl'");

foreach (['APP_KEY', 'JWT_SECRET', 'ENCRYPTION_KEY', 'DB_HOST', 'DB_NAME', 'DB_USER'] as $v) {
    $checks["var_$v"] = !empty($_ENV[$v])
        ? ok("$v definida [" . strlen($_ENV[$v]) . " chars]")
        : fail("$v no definida o vacía");
}

// ── 4. Base de datos ─────────────────────────────────────────────────────────
$pdo = null;
try {
    $pdo = new PDO(
        "mysql:host={$_ENV['DB_HOST']};port=" . ($_ENV['DB_PORT'] ?? 3306) . ";dbname={$_ENV['DB_NAME']};charset=utf8mb4",
        $_ENV['DB_USER'],
        $_ENV['DB_PASS'] ?? '',
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );
    $checks['db'] = ok('Conexión a BD exitosa', $_ENV['DB_NAME']);
} catch (\PDOException $e) {
    $checks['db'] = fail('Conexión a BD falló', $e->getMessage());
}

if ($pdo) {
    foreach (['admins', 'sessions', 'access_logs', 'password_resets', 'system_settings', 'contracts', 'signatures'] as $table) {
        try {
            $n = $pdo->query("SELECT COUNT(*) FROM `$table`")->fetchColumn();
            $checks["table_$table"] = ok("Tabla '$table'", "$n filas");
        } catch (\PDOException $e) {
            $checks["table_$table"] = fail("Tabla '$table' no existe", $e->getMessage());
        }
    }

    // Admins
    try {
        $admins = $pdo->query("SELECT id, email, activo FROM admins")->fetchAll(PDO::FETCH_ASSOC);
        if (!$admins) {
            $checks['admins_data'] = fail('No hay admins', 'Ejecutar INSERT en admins');
        } else {
            foreach ($admins as $a) {
                $checks['admin_' . $a['id']] = $a['activo']
                    ? ok('Admin activo: ' . $a['email'])
                    : warn('Admin INACTIVO: ' . $a['email'], 'activo=0');
            }
        }
    } catch (\Throwable $e) {
        $checks['admins_data'] = fail('Error leyendo admins', $e->getMessage());
    }

    // Rate limit — verificar si la IP está bloqueada
    $ip = $_SERVER['HTTP_CF_CONNECTING_IP']
        ?? $_SERVER['HTTP_X_FORWARDED_FOR']
        ?? $_SERVER['REMOTE_ADDR']
        ?? '?';
    $ip = trim(explode(',', $ip)[0]);
    try {
        $cutoff = date('Y-m-d H:i:s', strtotime('-15 minutes'));
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM access_logs WHERE ip_address=:ip AND accion='admin_login' AND created_at>:c");
        $stmt->execute([':ip' => $ip, ':c' => $cutoff]);
        $attempts = (int) $stmt->fetchColumn();
        $checks['rate_limit'] = $attempts >= 5
            ? fail("Rate limit activo para IP $ip", "$attempts/5 intentos — espera 15 min o limpia access_logs")
            : ok("Rate limit OK para IP $ip", "$attempts/5 intentos");
    } catch (\Throwable $e) {
        $checks['rate_limit'] = fail('Error en rate limit', $e->getMessage());
    }
}

// ── 5. Sesiones ──────────────────────────────────────────────────────────────
$isHttps = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
        || ($_SERVER['SERVER_PORT'] ?? 80) == 443;
$checks['https'] = $isHttps
    ? ok('HTTPS activo')
    : warn('No se detectó HTTPS', 'Las cookies secure pueden fallar');

ini_set('session.cookie_httponly', '1');
ini_set('session.use_strict_mode', '1');
ini_set('session.cookie_samesite', 'Lax');
ini_set('session.cookie_secure', $isHttps ? '1' : '0');
if (session_status() === PHP_SESSION_NONE) {
    session_name($_ENV['SESSION_COOKIE_NAME'] ?? 'contract_session');
    session_start();
}
$_SESSION['check_test'] = 'ok';
$checks['session'] = ($_SESSION['check_test'] === 'ok')
    ? ok('Sesiones PHP funcionan', 'cookie: ' . session_name())
    : fail('Sesiones PHP no funcionan');

// ── 6. Storage ───────────────────────────────────────────────────────────────
$storagePath = $rootPath . '/storage';
foreach (['logs', 'signatures', 'pdfs', 'temp'] as $dir) {
    $path = $storagePath . '/' . $dir;
    if (!is_dir($path)) {
        $checks["storage_$dir"] = fail("storage/$dir no existe");
    } elseif (!is_writable($path)) {
        $checks["storage_$dir"] = fail("storage/$dir no tiene permisos de escritura");
    } else {
        $checks["storage_$dir"] = ok("storage/$dir writable");
    }
}

// ── Limpiar rate limit (acción) ──────────────────────────────────────────────
if (isset($_GET['clear_ratelimit']) && $pdo) {
    $ip2 = trim(explode(',', ($_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? ''))[0]);
    $pdo->prepare("DELETE FROM access_logs WHERE ip_address=:ip AND accion='admin_login'")->execute([':ip' => $ip2]);
    header('Location: ?key=CHECK2024');
    exit;
}

// ── Output ───────────────────────────────────────────────────────────────────
$total  = count($checks);
$errors = count(array_filter($checks, fn($c) => $c['status'] === 'fail'));
$warns  = count(array_filter($checks, fn($c) => $c['status'] === 'warn'));
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Check — tucontrato.online</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:monospace;background:#0d1117;color:#c9d1d9;padding:24px;font-size:13px}
h1{color:#58a6ff;font-size:18px;margin-bottom:4px}
.meta{color:#8b949e;margin-bottom:20px;font-size:12px}
.summary{display:flex;gap:16px;margin-bottom:20px}
.badge{padding:6px 14px;border-radius:6px;font-weight:bold;font-size:13px}
.badge.ok{background:#1a3a1a;color:#3fb950}
.badge.fail{background:#3a1a1a;color:#f85149}
.badge.warn{background:#3a2a00;color:#e3b341}
table{width:100%;border-collapse:collapse}
tr{border-bottom:1px solid #21262d}
tr:hover{background:#161b22}
td{padding:7px 10px}
.s-ok{color:#3fb950}
.s-fail{color:#f85149;font-weight:bold}
.s-warn{color:#e3b341}
.detail{color:#8b949e;font-size:11px}
.actions{margin-top:20px;display:flex;gap:10px}
a.btn{background:#21262d;color:#58a6ff;padding:8px 16px;border-radius:6px;text-decoration:none;font-size:12px}
a.btn:hover{background:#30363d}
a.btn.danger{color:#f85149}
</style>
</head>
<body>
<h1>Sistema de Contratos — Validador</h1>
<div class="meta">Servidor: <?= php_uname('n') ?> | PHP: <?= PHP_VERSION ?> | <?= date('Y-m-d H:i:s') ?></div>

<div class="summary">
    <span class="badge <?= $errors ? 'fail' : 'ok' ?>"><?= $errors ?> errores</span>
    <span class="badge <?= $warns ? 'warn' : 'ok' ?>"><?= $warns ?> advertencias</span>
    <span class="badge ok"><?= $total - $errors - $warns ?> / <?= $total ?> OK</span>
</div>

<table>
<?php foreach ($checks as $check): ?>
<tr>
    <td style="width:22px">
        <?php if ($check['status'] === 'ok'): ?>
            <span class="s-ok">✓</span>
        <?php elseif ($check['status'] === 'fail'): ?>
            <span class="s-fail">✗</span>
        <?php else: ?>
            <span class="s-warn">⚠</span>
        <?php endif; ?>
    </td>
    <td class="s-<?= $check['status'] ?>"><?= htmlspecialchars($check['label']) ?></td>
    <td class="detail"><?= htmlspecialchars($check['detail']) ?></td>
</tr>
<?php endforeach; ?>
</table>

<div class="actions">
    <a class="btn" href="?key=CHECK2024">↺ Recargar</a>
    <a class="btn danger" href="?key=CHECK2024&clear_ratelimit=1">Limpiar rate limit de mi IP</a>
    <a class="btn" href="/admin/login">→ Ir al Login</a>
</div>

<p style="margin-top:24px;color:#f85149;font-size:11px">⚠ BORRAR este archivo en producción: <code>public/check.php</code></p>
</body>
</html>
