<?php

declare(strict_types=1);

require_once dirname(__DIR__) . '/lib/Security.php';
require_once dirname(__DIR__) . '/lib/CryptoService.php';

if (!function_exists('encrypt_text')) {
    function encrypt_text(string $plainText): string
    {
        return CryptoService::encrypt($plainText);
    }
}

if (!function_exists('decrypt_text')) {
    function decrypt_text(string $cipherText): ?string
    {
        try {
            return CryptoService::decrypt($cipherText);
        } catch (Throwable $e) {
            error_log('Error en decrypt_text: ' . $e->getMessage());
            return null;
        }
    }
}

if (!function_exists('csrf_token')) {
    function csrf_token(): string
    {
        return Security::csrfToken();
    }
}

if (!function_exists('csrf_field')) {
    function csrf_field(): string
    {
        return Security::csrfField();
    }
}

if (!function_exists('csrf_validate')) {
    function csrf_validate(?string $token = null): bool
    {
        return Security::validateCsrf($token);
    }
}

if (!function_exists('tiene_permiso')) {
    function tiene_permiso(string $permisoRequerido): bool
    {
        if (($_SESSION['admin']['rol'] ?? '') === 'Superadmin') {
            return true;
        }

        $permisos = $_SESSION['admin']['permisos'] ?? [];
        return is_array($permisos) && in_array($permisoRequerido, $permisos, true);
    }
}

if (!function_exists('exigir_permiso')) {
    function exigir_permiso(string $permisoRequerido, string $mensaje = 'Acceso denegado.'): void
    {
        if (tiene_permiso($permisoRequerido)) {
            return;
        }

        if (Security::expectsJson()) {
            Security::json(['success' => false, 'message' => $mensaje], 403);
        }

        $_SESSION['flash_message'] = ['type' => 'error', 'text' => $mensaje];
        header('Location: index.php');
        exit;
    }
}

if (!function_exists('verificarYRegistrarUsoConsulta')) {
    function verificarYRegistrarUsoConsulta(PDO $pdo, int $idAdmin): void
    {
        if ($idAdmin <= 0 || $idAdmin === 1) {
            return;
        }

        $stmt = $pdo->prepare(
            "SELECT p.nombre_plan, p.limite_consultas
             FROM suscripciones s
             JOIN planes p ON p.id = s.id_plan
             WHERE s.id_admin = ? AND s.estado IN ('activa', 'prueba')
             ORDER BY s.fecha_fin DESC, s.id DESC LIMIT 1"
        );
        $stmt->execute([$idAdmin]);
        $plan = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$plan || $plan['limite_consultas'] === null || (int) $plan['limite_consultas'] <= 0) {
            return;
        }

        $limit = (int) $plan['limite_consultas'];
        $period = date('Y-m');

        $pdo->beginTransaction();
        try {
            $usage = $pdo->prepare(
                'SELECT consultas_realizadas FROM uso_consultas WHERE id_admin = ? AND periodo = ? FOR UPDATE'
            );
            $usage->execute([$idAdmin, $period]);
            $used = $usage->fetchColumn();
            if ($used !== false && (int) $used >= $limit) {
                throw new RuntimeException("Has alcanzado el límite de {$limit} consultas públicas para este mes.");
            }

            $update = $pdo->prepare(
                'INSERT INTO uso_consultas (id_admin, periodo, consultas_realizadas)
                 VALUES (?, ?, 1)
                 ON DUPLICATE KEY UPDATE consultas_realizadas = consultas_realizadas + 1'
            );
            $update->execute([$idAdmin, $period]);
            $pdo->commit();
        } catch (Throwable $e) {
            if ($pdo->inTransaction()) {
                $pdo->rollBack();
            }
            throw $e;
        }
    }
}

if (!function_exists('generateUniqueConsultationCode')) {
    function generateUniqueConsultationCode(PDO $pdo): string
    {
        $stmt = $pdo->prepare('SELECT COUNT(*) FROM usuarios WHERE codigo_consulta = ?');
        for ($attempt = 0; $attempt < 20; $attempt++) {
            $code = str_pad((string) random_int(0, 99999999), 8, '0', STR_PAD_LEFT);
            $stmt->execute([$code]);
            if ((int) $stmt->fetchColumn() === 0) {
                return $code;
            }
        }
        throw new RuntimeException('No fue posible generar un código de consulta único.');
    }
}

if (!function_exists('es_superadmin')) {
    function es_superadmin(): bool
    {
        return ($_SESSION['admin']['rol'] ?? '') === 'Superadmin';
    }
}

if (!function_exists('restringir_modulo_superadmin')) {
    function restringir_modulo_superadmin(string $nombreModulo): void
    {
        if (!es_superadmin()) {
            return;
        }

        $message = "El módulo {$nombreModulo} está disponible únicamente para cuentas Admin.";
        if (Security::expectsJson() || isset($_GET['fetch_data']) || isset($_GET['fetch_edit_data'])) {
            Security::json(['success' => false, 'message' => $message], 403);
        }

        header('Location: index.php?status=warning&msg=' . urlencode($message));
        exit;
    }
}
