<?php

declare(strict_types=1);

// La sesión debe ser la misma sesión segura iniciada por config.php.
if (session_status() !== PHP_SESSION_ACTIVE) {
    if (!class_exists('Security')) {
        require_once __DIR__ . '/../config.php';
    }
    if (class_exists('Security')) {
        Security::startSession(defined('SESSION_NAME') ? SESSION_NAME : null);
    } else {
        session_start();
    }
}

if (!function_exists('fallar_verificacion')) {
    function fallar_verificacion(string $redirectUrl, string $jsonMessage, int $status = 401): void
    {
        $isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH'])
            && strtolower((string) $_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
        $expectsJson = $isAjax
            || str_contains(strtolower((string) ($_SERVER['HTTP_ACCEPT'] ?? '')), 'application/json');

        if ($expectsJson) {
            header('Content-Type: application/json; charset=utf-8');
            http_response_code($status);
            echo json_encode(['success' => false, 'message' => $jsonMessage], JSON_UNESCAPED_UNICODE);
        } else {
            header('Location: ' . $redirectUrl);
        }
        exit;
    }
}

if (!isset($_SESSION['admin']['uid'])) {
    fallar_verificacion('../login.php?error=login_required', 'Sesión no válida. Inicia sesión nuevamente.');
}

if (!isset($pdo) || !($pdo instanceof PDO)) {
    require_once __DIR__ . '/../config.php';
}

/*
 * Sincroniza el rol y los permisos en cada solicitud.
 * Así, al promover o revocar un Ayudante, una sesión que ya estaba abierta
 * adopta inmediatamente los permisos definidos en Roles y permisos.
 */
try {
    $identityStmt = $pdo->prepare(
        "SELECT u.id, u.id_rol, u.correo, u.nombre_usuario, u.telefono, r.nombre_rol
         FROM usuarios u
         JOIN roles r ON r.id = u.id_rol
         WHERE u.id = ?
         LIMIT 1"
    );
    $identityStmt->execute([(int) $_SESSION['admin']['uid']]);
    $identity = $identityStmt->fetch(PDO::FETCH_ASSOC);

    if (!$identity) {
        Security::destroySession();
        fallar_verificacion('../login.php?error=session_invalid', 'La cuenta ya no está disponible.', 401);
    }

    $permissions = [];
    $normalizedRole = mb_strtolower(trim((string) $identity['nombre_rol']), 'UTF-8');
    if ($normalizedRole !== 'superadmin') {
        $roleIds = [(int) $identity['id_rol']];

        // Un Ayudante sigue operando su propia cuenta como Admin y, además,
        // recibe los permisos delegados configurados para el rol Ayudante.
        if ($normalizedRole === 'ayudante de superadmin') {
            $adminRoleStmt = $pdo->query("SELECT id FROM roles WHERE nombre_rol = 'Admin' LIMIT 1");
            $adminRoleId = (int) ($adminRoleStmt ? $adminRoleStmt->fetchColumn() : 0);
            if ($adminRoleId > 0) {
                $roleIds[] = $adminRoleId;
            }
        }

        $roleIds = array_values(array_unique(array_filter($roleIds, static fn(int $id): bool => $id > 0)));
        if ($roleIds) {
            $placeholders = implode(',', array_fill(0, count($roleIds), '?'));
            $permissionStmt = $pdo->prepare(
                "SELECT DISTINCT p.clave_permiso
                 FROM rol_permiso rp
                 JOIN permisos p ON p.id = rp.id_permiso
                 WHERE rp.id_rol IN ($placeholders)
                 ORDER BY p.clave_permiso"
            );
            $permissionStmt->execute($roleIds);
            $permissions = $permissionStmt->fetchAll(PDO::FETCH_COLUMN, 0);
        }
    }

    $_SESSION['admin']['id_rol'] = (int) $identity['id_rol'];
    $_SESSION['admin']['rol'] = (string) $identity['nombre_rol'];
    $_SESSION['admin']['permisos'] = array_values(array_unique(array_map('strval', $permissions)));
    $_SESSION['admin']['correo'] = (string) $identity['correo'];
    $_SESSION['admin']['nombre_usuario'] = (string) $identity['nombre_usuario'];
    $_SESSION['admin']['telefono'] = (string) ($identity['telefono'] ?? '');
} catch (Throwable $e) {
    error_log('Error sincronizando rol y permisos: ' . $e->getMessage());
    fallar_verificacion('../login.php?error=db_error', 'No fue posible validar los permisos actuales.', 503);
}

$sessionRole = trim((string) ($_SESSION['admin']['rol'] ?? ''));
if (mb_strtolower($sessionRole, 'UTF-8') === 'superadmin') {
    $_SESSION['admin']['subscription_status'] = [
        'operational' => true,
        'state' => 'activa',
        'plan_name' => 'Superadmin',
        'message' => 'Acceso operativo.',
    ];
    return;
}

require_once __DIR__ . '/../lib/SubscriptionAccessService.php';

try {
    $subscriptionStatus = (new SubscriptionAccessService($pdo))->statusForAdmin((int) $_SESSION['admin']['uid']);
    $_SESSION['admin']['subscription_status'] = $subscriptionStatus;
} catch (Throwable $e) {
    error_log('Error comprobando la suscripción del Admin: ' . $e->getMessage());
    $_SESSION['admin']['subscription_status'] = [
        'operational' => false,
        'state' => 'error',
        'plan_name' => 'No disponible',
        'end_date' => null,
        'days_remaining' => null,
        'message' => 'No fue posible comprobar el estado de la suscripción.',
    ];
}
