<?php

declare(strict_types=1);

require_once __DIR__ . '/init.php';
require_once __DIR__ . '/../lib/ReferralCreditService.php';
require_once __DIR__ . '/../lib/SubscriptionService.php';

function af_subscription_add_period(DateTimeImmutable $date, string $cycle): DateTimeImmutable
{
    if ($cycle === 'anual') {
        $year = (int) $date->format('Y') + 1;
        $month = (int) $date->format('m');
        $day = (int) $date->format('d');
        $first = $date->setDate($year, $month, 1);
        return $first->setDate($year, $month, min($day, (int) $first->format('t')));
    }

    $day = (int) $date->format('d');
    $first = $date->modify('first day of next month');
    return $first->setDate((int) $first->format('Y'), (int) $first->format('m'), min($day, (int) $first->format('t')));
}

function af_subscription_admin_record(PDO $pdo, int $adminId): ?array
{
    $stmt = $pdo->prepare(
        "SELECT u.id, u.nombre_usuario, u.correo, u.telefono, r.nombre_rol
         FROM usuarios u JOIN roles r ON r.id = u.id_rol
         WHERE u.id = ? LIMIT 1"
    );
    $stmt->execute([$adminId]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    return $row ?: null;
}

function af_subscription_is_owner(array $user): bool
{
    return mb_strtolower(trim((string) ($user['nombre_rol'] ?? '')), 'UTF-8') === 'superadmin';
}


function af_subscription_owner_id(PDO $pdo): int
{
    $stmt = $pdo->query(
        "SELECT u.id
         FROM usuarios u
         JOIN roles r ON r.id = u.id_rol
         WHERE r.nombre_rol = 'Superadmin'
         ORDER BY u.id ASC
         LIMIT 1"
    );
    return (int) ($stmt->fetchColumn() ?: 0);
}

/**
 * Crea los datos mínimos para procesar el beneficio de referido en una
 * petición independiente. La renovación principal nunca espera este cálculo.
 */
function af_subscription_referral_job(int $subscriptionId, int $paymentId, string $cycle): ?array
{
    if ($cycle !== 'mensual') {
        return null;
    }

    return [
        'subscription_id' => $subscriptionId,
        'payment_id' => $paymentId,
    ];
}

if (isset($_GET['fetch_data'])) {
    Security::headers(true);
    $id = filter_input(INPUT_GET, 'fetch_data', FILTER_VALIDATE_INT) ?: 0;
    if ($id <= 0) Security::json(['success' => false, 'message' => 'Suscripción no válida.'], 422);

    $stmt = $pdo->prepare(
        "SELECT s.*, u.nombre_usuario, u.correo, u.telefono, r.nombre_rol
         FROM suscripciones s
         JOIN usuarios u ON u.id = s.id_admin
         JOIN roles r ON r.id = u.id_rol
         WHERE s.id = ? LIMIT 1"
    );
    $stmt->execute([$id]);
    $data = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$data) Security::json(['success' => false, 'message' => 'Suscripción no encontrada.'], 404);
    if (mb_strtolower((string) $data['nombre_rol'], 'UTF-8') === 'superadmin') {
        Security::json(['success' => false, 'message' => 'La suscripción del Superadmin es interna y no se edita desde este módulo.'], 403);
    }

    $data['fecha_inicio'] = date('Y-m-d', strtotime((string) $data['fecha_inicio']));
    $data['fecha_fin'] = date('Y-m-d', strtotime((string) $data['fecha_fin']));
    Security::json(['success' => true, 'data' => $data]);
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    Security::headers(true);
    Security::requireCsrf();
    $action = trim((string) ($_POST['action'] ?? ''));

    try {
        if ($action === 'procesar_beneficio_referido') {
            $subscriptionId = filter_input(INPUT_POST, 'id_suscripcion', FILTER_VALIDATE_INT) ?: 0;
            $paymentId = filter_input(INPUT_POST, 'id_pago', FILTER_VALIDATE_INT) ?: 0;
            if ($subscriptionId <= 0 || $paymentId <= 0) {
                throw new InvalidArgumentException('No se recibieron datos válidos para procesar el beneficio.');
            }

            $check = $pdo->prepare(
                "SELECT p.id, p.ciclo, p.estado_pago
                 FROM pagos p
                 WHERE p.id = ? AND p.id_suscripcion = ?
                 LIMIT 1"
            );
            $check->execute([$paymentId, $subscriptionId]);
            $payment = $check->fetch(PDO::FETCH_ASSOC);
            if (!$payment || (string) ($payment['estado_pago'] ?? '') !== 'confirmado') {
                throw new RuntimeException('El pago asociado no está disponible para procesar el beneficio.');
            }
            if ((string) ($payment['ciclo'] ?? '') !== 'mensual') {
                Security::json(['success' => true, 'message' => 'Esta modalidad no genera beneficio de referido.']);
            }

            // Libera la sesión antes del cálculo secundario para que el panel no quede bloqueado.
            if (session_status() === PHP_SESSION_ACTIVE) {
                session_write_close();
            }
            try {
                (new ReferralCreditService($pdo))->rewardFirstPayment($subscriptionId, $paymentId);
            } catch (Throwable $referralError) {
                error_log('No se pudo procesar el beneficio de referido: ' . $referralError->getMessage());
            }
            Security::json(['success' => true, 'message' => 'Beneficio de referido revisado.']);
        }

        if ($action === 'guardar_suscripcion') {
            $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT) ?: null;
            $postedAdminId = filter_input(INPUT_POST, 'id_admin', FILTER_VALIDATE_INT) ?: 0;
            $originalAdminId = filter_input(INPUT_POST, 'id_admin_original', FILTER_VALIDATE_INT) ?: 0;
            $planId = filter_input(INPUT_POST, 'id_plan', FILTER_VALIDATE_INT) ?: 0;
            $cycle = trim((string) ($_POST['ciclo_facturacion'] ?? ''));
            $startDate = trim((string) ($_POST['fecha_inicio'] ?? ''));
            $endDate = trim((string) ($_POST['fecha_fin'] ?? ''));
            $status = trim((string) ($_POST['estado'] ?? ''));
            $subscriberName = trim((string) ($_POST['nombre_usuario'] ?? ''));

            if ($planId <= 0 || $startDate === '' || $endDate === '' || $status === '') {
                throw new InvalidArgumentException('Completa todos los campos obligatorios.');
            }
            if (!in_array($status, ['activa', 'prueba', 'vencida', 'cancelada'], true)) {
                throw new InvalidArgumentException('El estado seleccionado no es válido.');
            }
            if (!in_array($cycle, ['mensual', 'anual', 'prueba', 'interno'], true)) {
                throw new InvalidArgumentException('Selecciona una modalidad válida.');
            }

            $startObject = DateTimeImmutable::createFromFormat('!Y-m-d', $startDate);
            $endObject = DateTimeImmutable::createFromFormat('!Y-m-d', $endDate);
            if (!$startObject || !$endObject || $startObject->format('Y-m-d') !== $startDate || $endObject->format('Y-m-d') !== $endDate || $endObject < $startObject) {
                throw new InvalidArgumentException('La fecha final debe ser igual o posterior a la fecha inicial.');
            }

            $planStmt = $pdo->prepare('SELECT id, nombre_plan, activo, es_interno, permite_mensual, permite_anual FROM planes WHERE id = ? LIMIT 1');
            $planStmt->execute([$planId]);
            $plan = $planStmt->fetch(PDO::FETCH_ASSOC);
            if (!$plan) throw new RuntimeException('El plan seleccionado no existe.');
            if ((int) ($plan['activo'] ?? 0) !== 1 && $status !== 'cancelada') {
                throw new RuntimeException('El plan está inactivo y no puede asignarse a una suscripción operativa.');
            }
            if ($cycle === 'mensual' && (int) ($plan['permite_mensual'] ?? 0) !== 1) {
                throw new RuntimeException('Este plan no tiene modalidad mensual habilitada.');
            }
            if ($cycle === 'anual' && (int) ($plan['permite_anual'] ?? 0) !== 1) {
                throw new RuntimeException('Este plan no tiene modalidad anual habilitada.');
            }

            if ($id !== null) {
                $existing = $pdo->prepare(
                    "SELECT s.id_admin, s.id_plan AS old_plan_id, u.nombre_usuario, u.correo, r.nombre_rol
                     FROM suscripciones s
                     JOIN usuarios u ON u.id = s.id_admin
                     JOIN roles r ON r.id = u.id_rol
                     WHERE s.id = ? LIMIT 1"
                );
                $existing->execute([$id]);
                $old = $existing->fetch(PDO::FETCH_ASSOC);
                if (!$old) throw new RuntimeException('La suscripción ya no existe.');
                if (mb_strtolower((string) $old['nombre_rol'], 'UTF-8') === 'superadmin') {
                    throw new RuntimeException('La suscripción interna del Superadmin está protegida.');
                }

                $adminId = (int) $old['id_admin'];
                if ($originalAdminId > 0 && $originalAdminId !== $adminId) {
                    throw new RuntimeException('La identidad del suscriptor cambió mientras editabas. Recarga la página e inténtalo nuevamente.');
                }
                if ($subscriberName === '') {
                    $subscriberName = trim((string) $old['nombre_usuario']);
                }
                if (mb_strlen($subscriberName, 'UTF-8') < 2 || mb_strlen($subscriberName, 'UTF-8') > 100) {
                    throw new InvalidArgumentException('El nombre del suscriptor debe tener entre 2 y 100 caracteres.');
                }

                if ((int) ($plan['es_interno'] ?? 0) === 1) {
                    if ((int) ($old['old_plan_id'] ?? 0) !== $planId) {
                        throw new RuntimeException('No se puede cambiar una suscripción comercial hacia un plan interno protegido.');
                    }
                    $cycle = 'interno';
                }

                $pdo->beginTransaction();

                // Bloquea la suscripción durante la edición para impedir que una
                // renovación simultánea sobrescriba las fechas que se están guardando.
                $lockSubscription = $pdo->prepare('SELECT id FROM suscripciones WHERE id = ? AND id_admin = ? FOR UPDATE');
                $lockSubscription->execute([$id, $adminId]);
                if (!$lockSubscription->fetchColumn()) {
                    throw new RuntimeException('La suscripción cambió o fue eliminada mientras la editabas.');
                }

                $storedStart = $startObject->format('Y-m-d 00:00:00');
                $storedEnd = $endObject->format('Y-m-d 23:59:59');
                $updateSubscription = $pdo->prepare(
                    'UPDATE suscripciones
                     SET id_plan = ?, ciclo_facturacion = ?, fecha_inicio = ?, fecha_fin = ?, estado = ?, fecha_actualizacion = CURRENT_TIMESTAMP
                     WHERE id = ? AND id_admin = ?'
                );
                $updateSubscription->execute([
                    $planId,
                    $cycle,
                    $storedStart,
                    $storedEnd,
                    $status,
                    $id,
                    $adminId,
                ]);

                $updateUser = $pdo->prepare('UPDATE usuarios SET nombre_usuario = ?, id_plan = ? WHERE id = ?');
                $updateUser->execute([$subscriberName, $planId, $adminId]);

                $verify = $pdo->prepare(
                    "SELECT id_plan, ciclo_facturacion, DATE(fecha_inicio) AS fecha_inicio,
                            DATE(fecha_fin) AS fecha_fin, estado
                     FROM suscripciones
                     WHERE id = ? AND id_admin = ? LIMIT 1"
                );
                $verify->execute([$id, $adminId]);
                $saved = $verify->fetch(PDO::FETCH_ASSOC);
                if (!$saved
                    || (int) $saved['id_plan'] !== $planId
                    || (string) $saved['ciclo_facturacion'] !== $cycle
                    || (string) $saved['fecha_inicio'] !== $startDate
                    || (string) $saved['fecha_fin'] !== $endDate
                    || (string) $saved['estado'] !== $status
                ) {
                    throw new RuntimeException('La base de datos no confirmó todos los cambios de la suscripción.');
                }

                $pdo->commit();
                Security::json([
                    'success' => true,
                    'message' => 'Suscripción actualizada correctamente. Se guardaron el nombre, plan, modalidad, estado y fechas; el correo se conservó.',
                    'data' => [
                        'id' => $id,
                        'id_admin' => $adminId,
                        'id_plan' => $planId,
                        'ciclo_facturacion' => $cycle,
                        'fecha_inicio' => $startDate,
                        'fecha_fin' => $endDate,
                        'estado' => $status,
                        'nombre_usuario' => $subscriberName,
                        'correo' => (string) $old['correo'],
                    ],
                ]);
            }

            $adminId = $postedAdminId;
            if ($adminId <= 0) {
                throw new InvalidArgumentException('Selecciona el Admin que recibirá la suscripción.');
            }
            $admin = af_subscription_admin_record($pdo, $adminId);
            if (!$admin) throw new RuntimeException('El Admin seleccionado no existe.');
            if (af_subscription_is_owner($admin)) {
                throw new RuntimeException('El Superadmin es el propietario del sistema y su plan interno no puede modificarse aquí.');
            }
            if (mb_strtolower((string) $admin['nombre_rol'], 'UTF-8') !== 'admin') {
                throw new RuntimeException('Las nuevas suscripciones solo pueden asignarse a cuentas con rol Admin.');
            }
            if ((int) ($plan['es_interno'] ?? 0) === 1) {
                throw new RuntimeException('Los planes internos están reservados y no pueden asignarse a nuevas suscripciones.');
            }

            $activeCheck = $pdo->prepare("SELECT COUNT(*) FROM suscripciones WHERE id_admin = ? AND estado IN ('activa','prueba')");
            $activeCheck->execute([$adminId]);
            if ((int) $activeCheck->fetchColumn() > 0) {
                throw new RuntimeException('Este Admin ya tiene una suscripción activa o en prueba. Edita la existente.');
            }

            $pdo->beginTransaction();
            $pdo->prepare(
                'INSERT INTO suscripciones (id_admin, id_plan, ciclo_facturacion, fecha_inicio, fecha_fin, estado, fecha_actualizacion)
                 VALUES (?, ?, ?, ?, ?, ?, NOW())'
            )->execute([
                $adminId,
                $planId,
                $cycle,
                $startObject->format('Y-m-d 00:00:00'),
                $endObject->format('Y-m-d 23:59:59'),
                $status,
            ]);
            $pdo->prepare('UPDATE usuarios SET id_plan = ? WHERE id = ?')->execute([$planId, $adminId]);
            $pdo->commit();
            Security::json(['success' => true, 'message' => 'Suscripción creada correctamente.']);
        }

        if ($action === 'guardar_pago') {
            $registeredBy = (int) ($_SESSION['admin']['uid'] ?? 0);
            $role = mb_strtolower(trim((string) ($_SESSION['admin']['rol'] ?? '')), 'UTF-8');
            if ($registeredBy <= 0 || $role !== 'superadmin') {
                throw new RuntimeException('Solo el Superadmin puede registrar renovaciones desde este módulo.');
            }

            // Libera la sesión antes de tocar las tablas comerciales. Esto evita
            // que una petición secundaria del panel bloquee la respuesta AJAX.
            if (session_status() === PHP_SESSION_ACTIVE) {
                session_write_close();
            }

            $result = (new SubscriptionService($pdo))->registerPaymentAndRenew($_POST, $registeredBy);
            $newEnd = !empty($result['new_end_date']) && strtotime((string) $result['new_end_date']) !== false
                ? date('d/m/Y', strtotime((string) $result['new_end_date']))
                : 'la fecha registrada';

            Security::json([
                'success' => true,
                'message' => !empty($result['duplicate'])
                    ? 'La renovación ya había sido registrada. La vigencia termina el ' . $newEnd . '.'
                    : 'Pago registrado. La nueva vigencia termina el ' . $newEnd . '.',
                'new_end_date' => $result['new_end_date'] ?? null,
                'payment_id' => $result['payment_id'] ?? null,
                'duplicate' => (bool) ($result['duplicate'] ?? false),
                'referral_job' => $result['referral_job'] ?? null,
            ]);
        }

        if ($action === 'delete_subscription') {
            $subscriptionId = filter_input(INPUT_POST, 'id_suscripcion', FILTER_VALIDATE_INT) ?: 0;
            if ($subscriptionId <= 0) throw new InvalidArgumentException('La suscripción seleccionada no es válida.');

            $stmt = $pdo->prepare(
                "SELECT s.id, s.id_admin, r.nombre_rol
                 FROM suscripciones s JOIN usuarios u ON u.id = s.id_admin JOIN roles r ON r.id = u.id_rol
                 WHERE s.id = ? LIMIT 1"
            );
            $stmt->execute([$subscriptionId]);
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$row) throw new RuntimeException('La suscripción ya no existe.');
            if (mb_strtolower((string) $row['nombre_rol'], 'UTF-8') === 'superadmin') {
                throw new RuntimeException('La suscripción interna del Superadmin está protegida.');
            }

            $pdo->beginTransaction();
            $pdo->prepare('DELETE FROM beneficios_referidos WHERE id_suscripcion_beneficiada = ? OR id_pago IN (SELECT id FROM pagos WHERE id_suscripcion = ?)')->execute([$subscriptionId, $subscriptionId]);
            $pdo->prepare('DELETE FROM renovaciones_credito WHERE id_suscripcion = ?')->execute([$subscriptionId]);
            $pdo->prepare('DELETE FROM pagos WHERE id_suscripcion = ?')->execute([$subscriptionId]);
            $delete = $pdo->prepare('DELETE FROM suscripciones WHERE id = ?');
            $delete->execute([$subscriptionId]);
            if ($delete->rowCount() !== 1) {
                throw new RuntimeException('No se pudo eliminar la suscripción seleccionada.');
            }
            $remainingPlan = $pdo->prepare('SELECT id_plan FROM suscripciones WHERE id_admin = ? ORDER BY id DESC LIMIT 1');
            $remainingPlan->execute([(int) $row['id_admin']]);
            $nextPlanId = $remainingPlan->fetchColumn();
            $pdo->prepare('UPDATE usuarios SET id_plan = ? WHERE id = ?')
                ->execute([$nextPlanId !== false ? (int) $nextPlanId : null, (int) $row['id_admin']]);
            $pdo->commit();
            Security::json(['success' => true, 'message' => 'Suscripción eliminada correctamente. La cuenta del Admin se conservó sin un plan activo.']);
        }

        if ($action === 'delete_subscriber') {
            $userId = filter_input(INPUT_POST, 'id_usuario', FILTER_VALIDATE_INT) ?: 0;
            if ($userId <= 0) throw new InvalidArgumentException('El suscriptor seleccionado no es válido.');

            $user = af_subscription_admin_record($pdo, $userId);
            if (!$user) throw new RuntimeException('El suscriptor ya no existe.');
            if (af_subscription_is_owner($user)) {
                throw new RuntimeException('El Superadmin es el propietario del sistema y no puede eliminarse.');
            }

            $pdo->beginTransaction();

            $subscriptionIdsStmt = $pdo->prepare('SELECT id FROM suscripciones WHERE id_admin = ? FOR UPDATE');
            $subscriptionIdsStmt->execute([$userId]);
            $subscriptionIds = array_map('intval', $subscriptionIdsStmt->fetchAll(PDO::FETCH_COLUMN));

            $ownerId = af_subscription_owner_id($pdo);
            if ($ownerId <= 0) throw new RuntimeException('No se encontró la cuenta propietaria del Superadmin.');

            $pdo->prepare('UPDATE usuarios SET id_referidor = NULL WHERE id_referidor = ?')->execute([$userId]);
            $pdo->prepare('UPDATE pagos SET registrado_por_admin_id = ? WHERE registrado_por_admin_id = ?')->execute([$ownerId, $userId]);
            $pdo->prepare('UPDATE movimientos_credito SET creado_por = NULL WHERE creado_por = ?')->execute([$userId]);
            $pdo->prepare('UPDATE movimientos_credito SET id_usuario_relacionado = NULL WHERE id_usuario_relacionado = ?')->execute([$userId]);

            $pdo->prepare('DELETE FROM beneficios_referidos WHERE id_referidor = ? OR id_referido = ?')->execute([$userId, $userId]);
            $pdo->prepare('DELETE FROM renovaciones_credito WHERE id_pagador = ? OR id_beneficiario = ?')->execute([$userId, $userId]);
            $pdo->prepare('DELETE FROM movimientos_credito WHERE id_usuario = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM configuracion_renovacion_admin WHERE id_admin = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM historial_renovaciones_cuenta WHERE id_admin = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM uso_consultas WHERE id_admin = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM usuarios_codigo_consulta_backup WHERE id_usuario = ?')->execute([$userId]);

            if ($subscriptionIds) {
                $placeholders = implode(',', array_fill(0, count($subscriptionIds), '?'));
                $pdo->prepare("DELETE FROM beneficios_referidos WHERE id_suscripcion_beneficiada IN ($placeholders) OR id_pago IN (SELECT id FROM pagos WHERE id_suscripcion IN ($placeholders))")
                    ->execute(array_merge($subscriptionIds, $subscriptionIds));
                $pdo->prepare("DELETE FROM renovaciones_credito WHERE id_suscripcion IN ($placeholders)")->execute($subscriptionIds);
                $pdo->prepare("DELETE FROM pagos WHERE id_suscripcion IN ($placeholders)")->execute($subscriptionIds);
                $pdo->prepare("DELETE FROM suscripciones WHERE id IN ($placeholders)")->execute($subscriptionIds);
            }

            $pdo->prepare('DELETE FROM asociaciones WHERE id_admin_propietario = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM correos_servicios WHERE id_admin_propietario = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM dominio_asunto WHERE id_dominio IN (SELECT id FROM dominios WHERE id_admin_propietario = ?)')->execute([$userId]);
            $pdo->prepare('DELETE FROM dominios WHERE id_admin_propietario = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM configuraciones_imap WHERE id_admin = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM usuarios WHERE id_admin_propietario = ?')->execute([$userId]);
            $pdo->prepare('DELETE FROM monederos WHERE id_usuario = ?')->execute([$userId]);

            $delete = $pdo->prepare('DELETE FROM usuarios WHERE id = ?');
            $delete->execute([$userId]);
            if ($delete->rowCount() !== 1) throw new RuntimeException('No se pudo eliminar el suscriptor.');

            $pdo->commit();
            Security::json(['success' => true, 'message' => 'Suscriptor y todos sus datos asociados eliminados correctamente.']);
        }

        throw new InvalidArgumentException('La acción solicitada no es válida.');
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        error_log('Gestionar suscripciones: ' . $e->getMessage());
        $publicMessage = $e->getMessage();
        if ($action === 'guardar_pago' && $e instanceof PDOException && (string) $e->getCode() === '23000') {
            $publicMessage = 'Esta renovación ya fue registrada. Actualiza la página y verifica la nueva vigencia antes de intentarlo otra vez.';
        }
        Security::json(['success' => false, 'message' => $publicMessage], 422);
    }
}

$titulo_pagina = 'Gestionar Suscriptores';
require_once __DIR__ . '/admin_header.php';

try {
    $suscripciones = $pdo->query(
        "SELECT s.*, u.nombre_usuario, u.correo, u.telefono, p.nombre_plan, r.nombre_rol
         FROM suscripciones s
         JOIN usuarios u ON u.id = s.id_admin
         JOIN roles r ON r.id = u.id_rol
         JOIN planes p ON p.id = s.id_plan
         ORDER BY CASE WHEN r.nombre_rol = 'Superadmin' THEN 0 ELSE 1 END, s.fecha_fin DESC, s.id DESC"
    )->fetchAll(PDO::FETCH_ASSOC);

    $planes = $pdo->query(
        "SELECT id, nombre_plan, precio_mensual, precio_anual, permite_mensual, permite_anual, activo, es_interno
         FROM planes ORDER BY es_interno ASC, orden_publico ASC, nombre_plan ASC"
    )->fetchAll(PDO::FETCH_ASSOC);
    $commercialPlans = array_values(array_filter($planes, static fn(array $p): bool => (int) $p['activo'] === 1 && (int) $p['es_interno'] === 0));

    $admins = $pdo->query(
        "SELECT u.id, u.nombre_usuario FROM usuarios u JOIN roles r ON r.id = u.id_rol
         WHERE r.nombre_rol = 'Admin' ORDER BY u.nombre_usuario"
    )->fetchAll(PDO::FETCH_ASSOC);

    $plantillas_suscripcion = $pdo->query("SELECT * FROM plantillas_whatsapp WHERE tipo_plantilla = 'suscripcion' AND modulo_uso <> 'promocion' ORDER BY nombre_plantilla")->fetchAll(PDO::FETCH_ASSOC);
    $plantillas_promocion = $pdo->query("SELECT * FROM plantillas_whatsapp WHERE tipo_plantilla = 'suscripcion' AND modulo_uso = 'promocion' ORDER BY nombre_plantilla")->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
    $error_message_db = 'Error al cargar los datos: ' . $e->getMessage();
    $suscripciones = $planes = $commercialPlans = $admins = $plantillas_suscripcion = $plantillas_promocion = [];
}

$total = count($suscripciones);
$active = $trial = $expired = 0;
foreach ($suscripciones as $item) {
    $state = mb_strtolower((string) $item['estado'], 'UTF-8');
    if ($state === 'activa' && strtotime((string) $item['fecha_fin']) >= strtotime('today')) $active++;
    elseif ($state === 'prueba' && strtotime((string) $item['fecha_fin']) >= strtotime('today')) $trial++;
    elseif ($state === 'vencida' || strtotime((string) $item['fecha_fin']) < strtotime('today')) $expired++;
}
?>
<link rel="stylesheet" href="../assets/css/superadmin-commercial.css?v=1.1.0">
<div class="super-commercial-ui px-4 md:px-6 pb-8">
    <div class="sc-shell">
        <?php if (!empty($error_message_db)): ?>
            <div class="sc-alert error"><i class="fas fa-database"></i><div><strong>Error de base de datos</strong><br><?= htmlspecialchars($error_message_db) ?></div></div>
        <?php else: ?>
            <section class="sc-card sc-hero"><div class="sc-hero-main"><span class="sc-icon"><i class="fas fa-id-card"></i></span><div><div class="sc-eyebrow">Operación comercial</div><h1 class="sc-title">Suscriptores</h1><p class="sc-copy">Administra planes, vigencias, pagos y comunicación. La cuenta propietaria del Superadmin permanece protegida.</p></div></div><div class="sc-actions"><button type="button" id="openSubscriptionModalBtn" class="sc-btn-primary"><i class="fas fa-plus"></i> Nueva suscripción</button></div></section>

            <section class="sc-stats">
                <article class="sc-stat"><span class="sc-stat-icon"><i class="fas fa-users"></i></span><div><div class="sc-stat-label">Suscripciones</div><div class="sc-stat-value"><?= $total ?></div><div class="sc-stat-note">Catálogo completo</div></div></article>
                <article class="sc-stat"><span class="sc-stat-icon green"><i class="fas fa-circle-check"></i></span><div><div class="sc-stat-label">Activas</div><div class="sc-stat-value"><?= $active ?></div><div class="sc-stat-note">Acceso vigente</div></div></article>
                <article class="sc-stat"><span class="sc-stat-icon amber"><i class="fas fa-flask"></i></span><div><div class="sc-stat-label">En prueba</div><div class="sc-stat-value"><?= $trial ?></div><div class="sc-stat-note">Periodo de evaluación</div></div></article>
                <article class="sc-stat"><span class="sc-stat-icon"><i class="fas fa-calendar-xmark"></i></span><div><div class="sc-stat-label">Vencidas</div><div class="sc-stat-value"><?= $expired ?></div><div class="sc-stat-note">Requieren revisión</div></div></article>
            </section>

            <section class="sc-card sc-records">
                <div class="sc-records-head"><span class="sc-section-icon"><i class="fas fa-list"></i></span><div><h2 class="sc-records-title">Registros de suscriptores</h2><p class="sc-records-copy">Los filtros se aplican automáticamente; utiliza Limpiar para restaurar la vista.</p></div></div>
                <div class="sc-toolbar cols-6 subscription-toolbar">
                    <div><label class="sc-label" for="search-input"><i class="fas fa-search"></i>Buscar</label><div class="sc-search"><i class="fas fa-search"></i><input type="search" id="search-input" class="sc-field" placeholder="Nombre o correo"></div></div>
                    <div><label class="sc-label" for="subscriptionPlan"><i class="fas fa-layer-group"></i>Plan</label><select id="subscriptionPlan" class="sc-field"><option value="">Todos</option><?php foreach ($planes as $plan): ?><option value="<?= htmlspecialchars((string) $plan['nombre_plan']) ?>"><?= htmlspecialchars((string) $plan['nombre_plan']) ?></option><?php endforeach; ?></select></div>
                    <div><label class="sc-label" for="subscriptionDue"><i class="fas fa-calendar"></i>Vence hasta</label><input type="date" id="subscriptionDue" class="sc-field"></div>
                    <div><label class="sc-label" for="subscriptionStatus"><i class="fas fa-signal"></i>Estado</label><select id="subscriptionStatus" class="sc-field"><option value="">Todos</option><option value="Activa">Activa</option><option value="Prueba">Prueba</option><option value="Vencida">Vencida</option><option value="Cancelada">Cancelada</option></select></div>
                    <div><label class="sc-label" for="subscriptionPageLength"><i class="fas fa-list-ol"></i>Mostrar</label><select id="subscriptionPageLength" class="sc-field"><option value="100" selected>100</option><option value="200">200</option><option value="400">400</option><option value="-1">Todos</option></select></div>
                    <div class="sc-filter-actions"><button type="button" id="clearSubscriptionFilters" class="sc-btn-secondary"><i class="fas fa-eraser"></i> Limpiar</button></div>
                </div>
                <div class="sc-summary"><span><?= $total ?> suscripciones registradas</span><span id="subscriptionInfo">Mostrando 0–0 de 0 registros</span></div>
                <div class="sc-table-wrap">
                    <table id="tablaSuscripciones">
                        <thead><tr><th>Admin suscriptor</th><th>Plan</th><th>Modalidad</th><th>Inicio</th><th>Fin</th><th>Estado</th><th class="text-right">Acciones</th></tr></thead>
                        <tbody>
                        <?php foreach ($suscripciones as $sub): ?>
                            <?php
                                $state = ucfirst(mb_strtolower((string) $sub['estado'], 'UTF-8'));
                                $isOwner = mb_strtolower((string) $sub['nombre_rol'], 'UTF-8') === 'superadmin';
                                $isExpired = strtotime((string) $sub['fecha_fin']) < strtotime('today');
                            ?>
                            <tr>
                                <td><strong><?= htmlspecialchars((string) $sub['nombre_usuario']) ?></strong><div class="sc-muted"><?= htmlspecialchars((string) $sub['correo']) ?></div><?php if ($isOwner): ?><span class="sc-pill gray sc-owner-pill"><i class="fas fa-lock"></i> Propietario protegido</span><?php endif; ?></td>
                                <td><?= htmlspecialchars((string) $sub['nombre_plan']) ?></td>
                                <td><?= htmlspecialchars(ucfirst((string) ($sub['ciclo_facturacion'] ?: 'Sin definir'))) ?></td>
                                <td><?= date('d/m/Y', strtotime((string) $sub['fecha_inicio'])) ?></td>
                                <td data-date="<?= date('Y-m-d', strtotime((string) $sub['fecha_fin'])) ?>" class="<?= $isExpired ? 'text-red-600 font-bold' : '' ?>"><?= date('d/m/Y', strtotime((string) $sub['fecha_fin'])) ?></td>
                                <td><span class="sc-pill <?= in_array(mb_strtolower($state, 'UTF-8'), ['activa','prueba'], true) && !$isExpired ? ($state === 'Prueba' ? 'amber' : 'green') : 'red' ?>"><?= $isExpired && $state === 'Activa' ? 'Vencida' : htmlspecialchars($state) ?></span></td>
                                <td class="sc-actions-cell">
                                    <div class="sc-actions-inline">
                                    <?php if ($isOwner): ?>
                                        <span class="sc-action protected" title="Acciones protegidas"><i class="fas fa-shield-halved"></i></span>
                                    <?php else: ?>
                                        <button type="button" class="sc-action whatsapp whatsapp-btn" title="Preparar mensaje de WhatsApp" data-telefono="<?= htmlspecialchars((string) ($sub['telefono'] ?? ''), ENT_QUOTES) ?>" data-nombre_cliente="<?= htmlspecialchars((string) $sub['nombre_usuario'], ENT_QUOTES) ?>" data-nombre_plan="<?= htmlspecialchars((string) $sub['nombre_plan'], ENT_QUOTES) ?>" data-fecha_fin="<?= date('d/m/Y', strtotime((string) $sub['fecha_fin'])) ?>"><i class="fab fa-whatsapp"></i></button>
                                        <button type="button" class="sc-action pay payment-btn" title="Registrar pago y renovar" data-id="<?= (int) $sub['id'] ?>" data-plan-id="<?= (int) $sub['id_plan'] ?>" data-current-end="<?= htmlspecialchars((string) $sub['fecha_fin'], ENT_QUOTES) ?>" data-name="<?= htmlspecialchars((string) $sub['nombre_usuario'], ENT_QUOTES) ?>"><i class="fas fa-wallet"></i></button>
                                        <button type="button" class="sc-action edit edit-btn" title="Editar suscripción" data-id="<?= (int) $sub['id'] ?>"><i class="fas fa-pen"></i></button>
                                        <button type="button" class="sc-action promo promote-btn" title="Enviar promoción" data-telefono="<?= htmlspecialchars((string) ($sub['telefono'] ?? ''), ENT_QUOTES) ?>" data-nombre_cliente="<?= htmlspecialchars((string) $sub['nombre_usuario'], ENT_QUOTES) ?>" data-nombre_plan="<?= htmlspecialchars((string) $sub['nombre_plan'], ENT_QUOTES) ?>" data-fecha_fin="<?= date('d/m/Y', strtotime((string) $sub['fecha_fin'])) ?>"><i class="fas fa-bullhorn"></i></button>
                                        <button type="button" class="sc-action delete delete-subscription-btn" title="Eliminar suscripción" data-id="<?= (int) $sub['id'] ?>"><i class="fas fa-trash"></i></button>
                                        <button type="button" class="sc-action user-delete delete-subscriber-btn" title="Eliminar suscriptor y datos asociados" data-id="<?= (int) $sub['id_admin'] ?>" data-nombre="<?= htmlspecialchars((string) $sub['nombre_usuario'], ENT_QUOTES) ?>"><i class="fas fa-user-xmark"></i></button>
                                    <?php endif; ?>
                                    </div>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
                <div class="sc-table-foot"><span>WhatsApp aparece primero. Toda renovación muestra la fecha actual y la nueva fecha antes de guardarse.</span><div id="subscriptionPagination" class="sc-pagination"></div></div>
            </section>
        <?php endif; ?>
    </div>
</div>

<div id="subscriptionModal" class="super-commercial-ui sc-modal fixed inset-0 hidden items-center justify-center z-[2147483000] px-3 py-4">
    <div class="sc-modal-shell"><div class="sc-modal-head"><div class="sc-modal-main"><span class="sc-modal-icon"><i class="fas fa-id-card"></i></span><div><div class="sc-modal-kicker">Suscriptores · formulario</div><div class="sc-modal-title" id="subscriptionModalTitle">Nueva suscripción</div><p class="sc-modal-copy">Asigna un Admin, plan, modalidad, vigencia y estado.</p></div></div><button type="button" class="sc-modal-close close-subscription-modal"><i class="fas fa-times"></i></button></div>
        <form id="subscriptionForm" class="contents" data-no-double-submit="true" novalidate>
            <?= Security::csrfField() ?>
            <input type="hidden" name="id" id="subscriptionId"><input type="hidden" name="id_admin_original" id="id_admin_original"><input type="hidden" name="action" value="guardar_suscripcion">
            <div class="sc-modal-body">
                <div class="sc-note"><i class="fas fa-circle-info"></i><span id="subscriptionFormNote">La cuenta propietaria del Superadmin no aparece en este formulario.</span></div>
                <div class="sc-grid-2"><div><label class="sc-label" for="id_admin"><i class="fas fa-user"></i>Admin *</label><select name="id_admin" id="id_admin" required class="sc-field"><option value="">Seleccionar Admin</option><?php foreach ($admins as $admin): ?><option value="<?= (int) $admin['id'] ?>"><?= htmlspecialchars((string) $admin['nombre_usuario']) ?></option><?php endforeach; ?></select><div id="subscriptionAdminHelp" class="sc-help">Selecciona el propietario de la nueva suscripción.</div></div><div><label class="sc-label" for="id_plan"><i class="fas fa-layer-group"></i>Plan *</label><select name="id_plan" id="id_plan" required class="sc-field"><option value="">Seleccionar plan</option><?php foreach ($planes as $plan): ?><option value="<?= (int) $plan['id'] ?>"><?= htmlspecialchars((string) $plan['nombre_plan']) ?></option><?php endforeach; ?></select></div></div>
                <div id="subscriptionIdentityFields" class="sc-identity-panel" hidden><div class="sc-grid-2"><div><label class="sc-label" for="subscriberName"><i class="fas fa-user-pen"></i>Nombre del suscriptor *</label><input type="text" name="nombre_usuario" id="subscriberName" maxlength="100" class="sc-field"><div class="sc-help">El nombre sí puede actualizarse desde este formulario.</div></div><div><label class="sc-label" for="subscriberEmail"><i class="fas fa-envelope"></i>Correo de acceso</label><input type="email" id="subscriberEmail" class="sc-field" readonly><div class="sc-help">El correo identifica la cuenta y se conserva sin cambios.</div></div></div></div>
                <div class="sc-grid-2"><div><label class="sc-label" for="ciclo_facturacion"><i class="fas fa-rotate"></i>Modalidad *</label><select name="ciclo_facturacion" id="ciclo_facturacion" required class="sc-field"><option value="mensual">Mensual</option><option value="anual">Anual</option><option value="prueba">Prueba</option><option value="interno">Interno</option></select></div><div><label class="sc-label" for="estado"><i class="fas fa-signal"></i>Estado *</label><select name="estado" id="estado" required class="sc-field"><option value="activa">Activa</option><option value="prueba">Prueba</option><option value="vencida">Vencida</option><option value="cancelada">Cancelada</option></select></div></div>
                <div class="sc-grid-2"><div><label class="sc-label" for="fecha_inicio"><i class="fas fa-calendar-plus"></i>Fecha de inicio *</label><input type="date" name="fecha_inicio" id="fecha_inicio" required class="sc-field"></div><div><label class="sc-label" for="fecha_fin"><i class="fas fa-calendar-check"></i>Fecha de fin *</label><input type="date" name="fecha_fin" id="fecha_fin" required class="sc-field"></div></div>
            </div>
            <div class="sc-modal-foot"><button type="button" class="sc-btn-secondary close-subscription-modal">Cancelar</button><button type="submit" class="sc-btn-primary"><i class="fas fa-save"></i> Guardar suscripción</button></div>
        </form>
    </div>
</div>

<div id="paymentModal" class="super-commercial-ui sc-modal fixed inset-0 hidden items-center justify-center z-[2147483000] px-3 py-4">
    <div class="sc-modal-shell wide"><div class="sc-modal-head"><div class="sc-modal-main"><span class="sc-modal-icon"><i class="fas fa-wallet"></i></span><div><div class="sc-modal-kicker">Suscriptores · renovación</div><div class="sc-modal-title">Registrar pago y renovar</div><p class="sc-modal-copy" id="paymentSubscriberName">Selecciona plan y modalidad; el monto se carga automáticamente y sigue siendo editable.</p></div></div><button type="button" class="sc-modal-close close-payment-modal"><i class="fas fa-times"></i></button></div>
        <form id="paymentForm" class="contents" data-no-double-submit="true" novalidate>
            <?= Security::csrfField() ?>
            <input type="hidden" name="id_suscripcion_pago" id="id_suscripcion_pago"><input type="hidden" name="action" value="guardar_pago"><input type="hidden" name="payment_key" id="payment_key">
            <div class="sc-modal-body">
                <div class="sc-note"><i class="fas fa-circle-info"></i><span>La vigencia se suma a la fecha final actual cuando todavía está activa; si venció, comienza desde hoy.</span></div>
                <div class="sc-grid-2"><div><label class="sc-label" for="new_plan_id_on_payment"><i class="fas fa-layer-group"></i>Plan *</label><select name="new_plan_id_on_payment" id="new_plan_id_on_payment" required class="sc-field"><option value="">Seleccionar plan</option><?php foreach ($commercialPlans as $plan): ?><option value="<?= (int) $plan['id'] ?>"><?= htmlspecialchars((string) $plan['nombre_plan']) ?></option><?php endforeach; ?></select></div><div><label class="sc-label" for="ciclo_pago"><i class="fas fa-rotate"></i>Modalidad *</label><select name="ciclo_pago" id="ciclo_pago" required class="sc-field"><option value="">Seleccionar modalidad</option><option value="mensual">Mensual</option><option value="anual">Anual</option></select></div></div>
                <div><label class="sc-label" for="monto_pago"><i class="fas fa-coins"></i>Monto del pago (S/) *</label><input type="number" min="0.01" step="0.01" name="monto_pago" id="monto_pago" required class="sc-field"><div class="sc-help">Se carga desde el plan, pero puedes ajustarlo antes de guardar.</div></div>
                <div class="sc-renew-date-preview"><span><small>Fecha actual</small><strong id="paymentCurrentEnd">Sin fecha</strong></span><i class="fas fa-arrow-right"></i><span><small>Nueva vigencia</small><strong id="paymentNewEnd">Selecciona modalidad</strong></span></div>
            </div>
            <div class="sc-modal-foot"><button type="button" class="sc-btn-secondary close-payment-modal">Cancelar</button><button type="submit" class="sc-btn-success"><i class="fas fa-check"></i> Registrar pago</button></div>
        </form>
    </div>
</div>

<style>

.super-commercial-ui .sc-toolbar.cols-6{grid-template-columns:minmax(170px,.9fr) minmax(145px,.75fr) minmax(145px,.75fr) minmax(135px,.65fr) 100px auto}
.super-commercial-ui .subscription-toolbar .sc-filter-actions{align-self:end}
.super-commercial-ui .sc-owner-pill{margin-top:5px}
.super-commercial-ui .sc-action.protected{color:#475569;background:#f1f5f9;border-color:#dbe4ef}
.super-commercial-ui .sc-renew-date-preview{display:grid;grid-template-columns:1fr 28px 1fr;align-items:center;gap:10px;padding:12px;border:1px solid #bbf7d0;border-radius:12px;background:#f0fdf4}
.super-commercial-ui .sc-renew-date-preview>i{text-align:center;color:#16a34a}
.super-commercial-ui .sc-renew-date-preview small,.super-commercial-ui .sc-renew-date-preview strong{display:block}
.super-commercial-ui .sc-renew-date-preview small{font-size:9px;font-weight:900;text-transform:uppercase;color:#64806d}
.super-commercial-ui .sc-renew-date-preview strong{margin-top:4px;color:#166534;font-size:13px}
.super-commercial-ui .sc-help{margin-top:5px;color:#64748b;font-size:10px}
.super-commercial-ui .sc-identity-panel{padding:12px;border:1px solid #dbe4ef;border-radius:12px;background:#f8fafc}
.super-commercial-ui .sc-field:disabled{background:#eef2f7;color:#64748b;cursor:not-allowed}
.super-commercial-ui .sc-field[readonly]{background:#f8fafc;color:#475569}
.swal2-container{position:fixed!important;z-index:2147483647!important}.swal2-popup{isolation:isolate}
.super-commercial-ui .sc-actions-cell{white-space:nowrap;text-align:right;min-width:244px}
.super-commercial-ui .sc-actions-inline{display:inline-flex;align-items:center;gap:4px;flex-wrap:nowrap}
.super-commercial-ui .sc-actions-inline .sc-action{margin-left:0;flex:0 0 auto}

.af-template-picker{display:grid;gap:12px;text-align:left}
.af-template-search{position:relative}
.af-template-search>i{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:#94a3b8}
.af-template-search input{width:100%;min-height:43px;padding:10px 13px 10px 38px;border:1px solid #dbe3ee;border-radius:12px;color:#172033;background:#fff;outline:none;font-size:13px}
.af-template-search input:focus{border-color:#ef4444;box-shadow:0 0 0 3px rgba(239,68,68,.1)}
.af-template-list{display:grid;gap:8px;max-height:355px;overflow:auto;padding-right:4px}
.af-template-card{width:100%;display:grid;grid-template-columns:38px minmax(0,1fr) 22px;align-items:start;gap:11px;padding:12px;border:1px solid #e2e8f0;border-radius:13px;background:#fff;text-align:left;cursor:pointer;transition:.18s ease}
.af-template-card:hover{border-color:#fda4af;background:#fff7f8}
.af-template-card.is-selected{border-color:#ef4444;background:#fff1f2;box-shadow:0 0 0 2px rgba(239,68,68,.09)}
.af-template-card[hidden]{display:none}
.af-template-icon{width:38px;height:38px;display:grid;place-items:center;border-radius:11px;color:#dc2626;background:#fee2e2}
.af-template-copy{min-width:0}
.af-template-copy strong{display:block;color:#172033;font-size:12.5px}
.af-template-copy span{display:block;margin-top:4px;color:#64748b;font-size:10.5px;line-height:1.45;white-space:normal}
.af-template-copy small{display:inline-flex;margin-top:6px;padding:3px 7px;border-radius:999px;color:#475569;background:#f1f5f9;font-size:8.5px;font-weight:900;text-transform:uppercase;letter-spacing:.05em}
.af-template-check{margin-top:9px;color:#cbd5e1}
.af-template-card.is-selected .af-template-check{color:#dc2626}
.af-template-empty{padding:20px;border:1px dashed #cbd5e1;border-radius:12px;color:#64748b;background:#f8fafc;text-align:center;font-size:12px}
.af-template-tip{display:flex;align-items:flex-start;gap:8px;padding:10px 12px;border-radius:11px;color:#475569;background:#f8fafc;font-size:10.5px;line-height:1.45}
.af-template-tip i{margin-top:2px;color:#0ea5e9}

@media(max-width:1150px){
  .super-commercial-ui .sc-toolbar.cols-6{grid-template-columns:repeat(3,minmax(0,1fr))}
  .super-commercial-ui .subscription-toolbar .sc-filter-actions{grid-column:auto}
}
@media(max-width:700px){
  .super-commercial-ui .sc-toolbar.cols-6{grid-template-columns:1fr}
  .super-commercial-ui .sc-renew-date-preview{grid-template-columns:1fr}
  .super-commercial-ui .sc-renew-date-preview>i{transform:rotate(90deg)}
}

</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script><script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(function(){
    const plans=<?= json_encode(array_map(static fn(array $p): array => ['id'=>(int)$p['id'],'name'=>(string)$p['nombre_plan'],'monthly'=>(float)$p['precio_mensual'],'annual'=>(float)$p['precio_anual'],'allowMonthly'=>(int)$p['permite_mensual']===1,'allowAnnual'=>(int)$p['permite_anual']===1,'internal'=>(int)$p['es_interno']===1], $planes), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    const templates=<?= json_encode($plantillas_suscripcion, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    const promoTemplates=<?= json_encode($plantillas_promocion, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    let dueFilter='';
    $.fn.dataTable.ext.search.push(function(settings,data,index){if(settings.nTable.id!=='tablaSuscripciones'||!dueFilter)return true;const cell=settings.aoData[index].anCells[4];const date=cell?.dataset?.date||'';return date!==''&&date<=dueFilter});
    const table=$('#tablaSuscripciones').DataTable({dom:'t',language:{url:'//cdn.datatables.net/plug-ins/1.11.3/i18n/es_es.json'},pageLength:100,lengthMenu:[[100,200,400,-1],[100,200,400,'Todos']],order:[],autoWidth:false,columnDefs:[{orderable:false,targets:[6]}]});
    function renderPagination(){const info=table.page.info(),total=info.recordsDisplay||0,start=total?info.start+1:0,end=total?info.end:0,pages=info.pages||0,current=info.page||0;$('#subscriptionInfo').text(`Mostrando ${start}–${end} de ${total} registros`);let h=`<button class="sc-page" data-page="prev" ${current===0||!pages?'disabled':''}><i class="fas fa-chevron-left"></i></button>`;if(!pages)h+='<button class="sc-page active" disabled>1</button>';else for(let i=0;i<pages;i++){if(pages<=5||i===0||i===pages-1||Math.abs(i-current)<=1)h+=`<button class="sc-page ${i===current?'active':''}" data-page="${i}">${i+1}</button>`;else if(i===current-2||i===current+2)h+='<span>…</span>';}h+=`<button class="sc-page" data-page="next" ${current>=pages-1||!pages?'disabled':''}><i class="fas fa-chevron-right"></i></button>`;$('#subscriptionPagination').html(h)}
    $('#search-input').on('input',function(){table.search(this.value).draw()});
    $('#subscriptionPlan').on('change',function(){table.column(1).search(this.value?`^${$.fn.dataTable.util.escapeRegex(this.value)}$`:'',true,false).draw()});
    $('#subscriptionStatus').on('change',function(){table.column(5).search(this.value?`^${this.value}$`:'',true,false).draw()});
    $('#subscriptionDue').on('change',function(){dueFilter=this.value;table.draw()});
    $('#subscriptionPageLength').on('change',function(){table.page.len(parseInt(this.value,10)).draw()});
    $('#clearSubscriptionFilters').on('click',function(){$('#search-input,#subscriptionPlan,#subscriptionStatus,#subscriptionDue').val('');$('#subscriptionPageLength').val('100');dueFilter='';table.search('').columns().search('').page.len(100).draw()});
    table.on('draw page.dt length.dt search.dt',renderPagination);renderPagination();
    $('#subscriptionPagination').on('click','.sc-page',function(){if(this.disabled)return;const p=$(this).data('page');if(p==='prev')table.page('previous').draw('page');else if(p==='next')table.page('next').draw('page');else table.page(parseInt(p,10)).draw('page')});

    function restoreModalLayer(el){
        const node=el.get(0);
        if(node){node.style.removeProperty('display');node.style.removeProperty('z-index');node.style.removeProperty('visibility')}
    }
    function openModal(el){
        restoreModalLayer(el);
        el.removeAttr('data-busy').attr('aria-hidden','false');
        $('body').addClass('overflow-hidden sc-commercial-modal-open');
        el.removeClass('hidden').addClass('flex');
    }
    function closeModal(el,force=false){
        if(!force&&el.attr('data-busy')==='1')return;
        el.removeAttr('data-busy').attr('aria-hidden','true').addClass('hidden').removeClass('flex');
        if(!$('.sc-modal.flex').length)$('body').removeClass('overflow-hidden sc-commercial-modal-open');
    }
    function hardHideModal(el){
        const node=el.get(0);
        el.removeAttr('data-busy').attr('aria-hidden','true').addClass('hidden').removeClass('flex');
        if(node){node.style.setProperty('display','none','important');node.style.setProperty('visibility','hidden','important');node.style.setProperty('z-index','-1','important')}
        $('body').removeClass('overflow-hidden sc-commercial-modal-open');
        if(document.activeElement instanceof HTMLElement)document.activeElement.blur();
    }
    async function showTopDialog(options){
        const originalDidOpen=options.didOpen;
        return Swal.fire({
            target:document.body,
            ...options,
            didOpen:(popup)=>{
                const container=Swal.getContainer();
                if(container){container.style.setProperty('z-index','2147483647','important');container.style.setProperty('position','fixed','important')}
                if(typeof originalDidOpen==='function')originalDidOpen(popup);
            }
        });
    }
    function randomKey(){if(window.crypto?.getRandomValues){const b=new Uint8Array(18);crypto.getRandomValues(b);return 'pay_'+Array.from(b).map(x=>x.toString(16).padStart(2,'0')).join('')}return 'pay_'+Date.now()+'_'+Math.random().toString(36).slice(2)}
    function parseDate(value){if(!value)return null;const d=new Date(String(value).replace(' ','T'));return Number.isNaN(d.getTime())?null:d}
    function addMonths(date,months){const d=new Date(date.getTime()),day=d.getDate();d.setDate(1);d.setMonth(d.getMonth()+months);const last=new Date(d.getFullYear(),d.getMonth()+1,0).getDate();d.setDate(Math.min(day,last));return d}
    function fmt(date){return date?new Intl.DateTimeFormat('es-PE',{day:'2-digit',month:'2-digit',year:'numeric'}).format(date):'Sin fecha'}
    function escapeHtml(v){return String(v??'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#039;')}
    function previewHtml(v){return escapeHtml(v).replace(/\*([^*\n]+)\*/g,'<strong>$1</strong>').replace(/\n/g,'<br>')}

    const whatsappBrand=<?= json_encode((string) ($ui_title_system ?? 'Ave Fénix'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;

    function replaceWhatsAppPlaceholder(message,key,value){
        const cleanValue=String(value||'Sin dato').replace(/\*/g,'').trim()||'Sin dato';
        const escapedKey=String(key).replace(/[.*+?^${}()|[\]\\]/g,'\\$&');
        return String(message||'')
            .replace(new RegExp(`\\*\\{${escapedKey}\\}\\*`,'g'),`*${cleanValue}*`)
            .replace(new RegExp(`\\{${escapedKey}\\}`,'g'),`*${cleanValue}*`);
    }

    function professionalWhatsAppMessage(data,template,mode='suscripcion'){
        const name=String(data.nombre_cliente||'cliente').trim()||'cliente';
        const plan=String(data.nombre_plan||'plan contratado').trim()||'plan contratado';
        const endDate=String(data.fecha_fin||'sin fecha registrada').trim()||'sin fecha registrada';
        const templateName=String(template.nombre_plantilla||'').toLowerCase();

        let message=String(template.mensaje||'').trim();
        message=replaceWhatsAppPlaceholder(message,'nombre_cliente',name);
        message=replaceWhatsAppPlaceholder(message,'nombre_plan',plan);
        message=replaceWhatsAppPlaceholder(message,'fecha_fin',endDate);
        message=message.replace(/\*{2,}/g,'*').replace(/\n{3,}/g,'\n\n').trim();

        let heading='📣 *INFORMACIÓN DE TU SUSCRIPCIÓN*';
        if(mode==='promocion')heading='🎁 *BENEFICIO ESPECIAL PARA TU PLAN*';
        else if(/vencid|expir/.test(templateName))heading='🚨 *SUSCRIPCIÓN VENCIDA*';
        else if(/reactiv|confirm/.test(templateName))heading='✅ *SUSCRIPCIÓN REACTIVADA*';
        else if(/próxim|proxim|record|renov/.test(templateName))heading='⏰ *RECORDATORIO DE RENOVACIÓN*';

        const firstLine=message.split('\n')[0]?.trim()||'';
        const hasHeading=/^[^\n]{0,8}\*[^*\n]{4,90}\*\s*$/.test(firstLine);
        if(!hasHeading)message=`${heading}\n\n${message}`;

        const normalized=message.toLowerCase();
        const hasPlan=normalized.includes(plan.toLowerCase());
        const hasDate=normalized.includes(endDate.toLowerCase());

        if(!hasPlan||!hasDate){
            const details=[];
            if(!hasPlan)details.push(`📦 *Plan:* *${plan.replace(/\*/g,'')}*`);
            if(!hasDate)details.push(`📅 *Vigencia:* *${endDate.replace(/\*/g,'')}*`);
            message+=`\n\n${details.join('\n')}`;
        }

        if(!/(responde|escríbenos|escribenos|contáctanos|contactanos|quedamos atentos|solicita)/i.test(message)){
            message+='\n\n💬 *Siguiente paso:* responde a este mensaje para confirmar la renovación o solicitar ayuda.';
        }

        if(whatsappBrand&&!message.toLowerCase().includes(whatsappBrand.toLowerCase())){
            message+=`\n\n✨ *${String(whatsappBrand).replace(/\*/g,'')}*`;
        }

        return message.replace(/\n{3,}/g,'\n\n').trim();
    }

    async function copyText(text){if(navigator.clipboard?.writeText)return navigator.clipboard.writeText(text);const a=document.createElement('textarea');a.value=text;a.style.position='fixed';a.style.opacity='0';document.body.appendChild(a);a.select();document.execCommand('copy');a.remove()}
    function dispatchReferralJob(job){
        if(!job||!job.subscription_id||!job.payment_id)return;
        const data=new FormData();
        data.append('action','procesar_beneficio_referido');
        data.append('id_suscripcion',String(job.subscription_id));
        data.append('id_pago',String(job.payment_id));
        data.append('_csrf',<?= json_encode(Security::csrfToken()) ?>);
        if(navigator.sendBeacon){navigator.sendBeacon('ajax/procesar_beneficio_referido.php',data);return}
        fetch('ajax/procesar_beneficio_referido.php',{method:'POST',body:data,credentials:'same-origin',keepalive:true,headers:{'X-Requested-With':'XMLHttpRequest','Accept':'application/json'}}).catch(()=>{});
    }

    function updateSubscriptionCycles(){const p=plans.find(x=>x.id===$('#id_plan').val()*1);const cycle=$('#ciclo_facturacion');if(!p)return;cycle.find('option[value="mensual"]').prop('disabled',!p.allowMonthly);cycle.find('option[value="anual"]').prop('disabled',!p.allowAnnual);if(p.internal)cycle.val('interno');else if(cycle.val()==='interno'||(cycle.val()==='mensual'&&!p.allowMonthly)||(cycle.val()==='anual'&&!p.allowAnnual))cycle.val(p.allowMonthly?'mensual':(p.allowAnnual?'anual':'prueba'))}
    function openSubscription(edit=false,data={}){
        const form=$('#subscriptionForm')[0];
        form.reset();
        $('#subscriptionId,#id_admin_original').val('');
        $('#id_admin').prop('disabled',false).prop('required',true);
        $('#subscriptionIdentityFields').prop('hidden',true);
        $('#subscriberName,#subscriberEmail').val('');
        $('#subscriptionModalTitle').text(edit?'Editar suscripción':'Nueva suscripción');
        if(edit){
            $('#subscriptionId').val(data.id);
            $('#id_admin_original').val(data.id_admin);
            $('#id_admin').val(data.id_admin).prop('disabled',true).prop('required',false);
            $('#id_plan').val(data.id_plan);
            $('#ciclo_facturacion').val(data.ciclo_facturacion||'mensual');
            $('#fecha_inicio').val(data.fecha_inicio);
            $('#fecha_fin').val(data.fecha_fin);
            $('#estado').val(data.estado);
            $('#subscriberName').val(data.nombre_usuario||'');
            $('#subscriberEmail').val(data.correo||'');
            $('#subscriptionIdentityFields').prop('hidden',false);
            $('#subscriptionFormNote').text('El suscriptor y su correo quedan protegidos. Puedes actualizar el nombre, plan, modalidad, estado y fechas.');
            $('#subscriptionAdminHelp').text('El suscriptor no puede cambiarse durante la edición.');
        }else{
            const today=new Date().toISOString().slice(0,10);
            $('#fecha_inicio').val(today);
            $('#subscriptionFormNote').text('La cuenta propietaria del Superadmin no aparece en este formulario.');
            $('#subscriptionAdminHelp').text('Selecciona el propietario de la nueva suscripción.');
        }
        updateSubscriptionCycles();
        openModal($('#subscriptionModal'));
        setTimeout(()=>$(edit?'#subscriberName':'#id_admin').trigger('focus'),60);
    }
    $('#id_plan').on('change',updateSubscriptionCycles);
    $('#openSubscriptionModalBtn').on('click',()=>openSubscription(false));
    $('.close-subscription-modal').on('click',()=>closeModal($('#subscriptionModal')));$('.close-payment-modal').on('click',()=>closeModal($('#paymentModal')));$('.close-promote-modal').on('click',()=>closeModal($('#promoteModal')));$('.sc-modal').on('click',function(e){if(e.target===this)closeModal($(this))});$(document).on('keydown.superCommercial',function(e){if(e.key==='Escape')$('.sc-modal.flex').each(function(){closeModal($(this))})});
    $('#tablaSuscripciones').on('click','.edit-btn',function(){$.getJSON(`gestionar_suscripciones.php?fetch_data=${$(this).data('id')}`).done(r=>r.success?openSubscription(true,r.data):Swal.fire('Error',r.message,'error')).fail(x=>Swal.fire('Error',x.responseJSON?.message||'No se pudo obtener la suscripción.','error'))});

    let paymentCurrentEnd='';
    function updatePaymentForm(){const p=plans.find(x=>x.id===$('#new_plan_id_on_payment').val()*1),cycle=$('#ciclo_pago');if(!p){cycle.val('');$('#monto_pago').val('');$('#paymentNewEnd').text('Selecciona modalidad');return}cycle.find('option[value="mensual"]').prop('disabled',!p.allowMonthly);cycle.find('option[value="anual"]').prop('disabled',!p.allowAnnual);let selected=cycle.val();if((selected==='mensual'&&!p.allowMonthly)||(selected==='anual'&&!p.allowAnnual)||!selected)selected=p.allowMonthly?'mensual':(p.allowAnnual?'anual':'');cycle.val(selected);const amount=selected==='anual'?p.annual:p.monthly;$('#monto_pago').val(amount>0?Number(amount).toFixed(2):'');const today=new Date();today.setHours(0,0,0,0);const current=parseDate(paymentCurrentEnd);if(current)current.setHours(0,0,0,0);const base=current&&current>today?current:today;$('#paymentCurrentEnd').text(current?fmt(current):'Sin fecha');$('#paymentNewEnd').text(selected?fmt(addMonths(base,selected==='anual'?12:1)):'Selecciona modalidad')}
    $('#new_plan_id_on_payment,#ciclo_pago').on('change',updatePaymentForm);
    $('#tablaSuscripciones').on('click','.payment-btn',function(){$('#paymentForm')[0].reset();$('#id_suscripcion_pago').val($(this).data('id'));$('#new_plan_id_on_payment').val(String($(this).data('plan-id')));$('#payment_key').val(randomKey());paymentCurrentEnd=String($(this).data('current-end')||'');$('#paymentSubscriberName').text('Renovación para '+($(this).data('name')||'suscriptor'));updatePaymentForm();openModal($('#paymentModal'))});

    async function readJsonResponse(response){
        const raw=await response.text();
        let data=null;
        try{data=raw?JSON.parse(raw):null}catch(error){
            throw new Error(raw&&raw.length<260?raw:'El servidor devolvió una respuesta no válida.');
        }
        if(!response.ok||!data?.success)throw new Error(data?.message||'No se pudo completar la operación.');
        return data;
    }

    function wait(ms){return new Promise(resolve=>setTimeout(resolve,ms))}

    async function fetchWithTimeout(url, options={}, timeoutMs=5000){
        const controller=new AbortController();
        const externalSignal=options.signal;
        const timer=setTimeout(()=>controller.abort(),timeoutMs);
        if(externalSignal){
            if(externalSignal.aborted)controller.abort();
            else externalSignal.addEventListener('abort',()=>controller.abort(),{once:true});
        }
        try{
            return await fetch(url,{...options,signal:controller.signal});
        }finally{
            clearTimeout(timer);
        }
    }

    async function checkRenewalStatus(paymentKey){
        const body=new URLSearchParams({
            action:'consultar_pago',
            payment_key:paymentKey,
            _csrf:<?= json_encode(Security::csrfToken()) ?>
        });
        const response=await fetchWithTimeout('ajax/renovar_suscripcion.php',{
            method:'POST',
            credentials:'same-origin',
            headers:{
                'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8',
                'X-Requested-With':'XMLHttpRequest',
                'Accept':'application/json'
            },
            body:body.toString(),
            cache:'no-store'
        },4500);
        const data=await readJsonResponse(response);
        return data.processed&&data.result?data.result:null;
    }

    async function pollRenewalStatus(paymentKey,onProgress){
        const delays=[1000,1400,1800,2400,3200];
        for(let index=0;index<delays.length;index++){
            await wait(delays[index]);
            if(typeof onProgress==='function')onProgress(index);
            try{
                const result=await checkRenewalStatus(paymentKey);
                if(result)return result;
            }catch(error){
                // Una consulta puntual puede coincidir con el cierre de la transacción.
                // Se continúa con el siguiente intento corto.
            }
        }
        return null;
    }

    $('#subscriptionForm').on('submit',async function(e){
        e.preventDefault();
        const form=this;
        if(!form.reportValidity())return;
        const modal=$(form).closest('.sc-modal');
        const button=$(form).find('button[type="submit"]');
        if(button.prop('disabled'))return;

        const original=button.html();
        const payload=new FormData(form);
        const subscriptionId=String($('#subscriptionId').val()||'');
        if(subscriptionId){
            payload.set('id',subscriptionId);
            payload.set('id_admin_original',String($('#id_admin_original').val()||''));
            payload.set('nombre_usuario',String($('#subscriberName').val()||''));
        }

        modal.attr('data-busy','1');
        button.prop('disabled',true).html('<i class="fas fa-spinner fa-spin"></i> Guardando…');

        try{
            const target=subscriptionId?'ajax/editar_suscripcion.php':'gestionar_suscripciones.php';
            const response=await fetchWithTimeout(target,{
                method:'POST',
                body:payload,
                credentials:'same-origin',
                headers:{'X-Requested-With':'XMLHttpRequest','Accept':'application/json'},
                cache:'no-store'
            },15000);
            const result=await readJsonResponse(response);
            hardHideModal(modal);
            await wait(70);
            await showTopDialog({
                icon:'success',
                title:'Cambios guardados',
                text:result.message||'La suscripción fue actualizada correctamente.',
                confirmButtonColor:'#dc2626'
            });
            location.reload();
        }catch(error){
            hardHideModal(modal);
            await wait(70);
            await showTopDialog({
                icon:'error',
                title:'No se pudo guardar',
                text:error?.message||'No se pudo actualizar la suscripción.',
                confirmButtonColor:'#dc2626'
            });
            restoreModalLayer(modal);
            openModal(modal);
        }finally{
            modal.removeAttr('data-busy');
            button.prop('disabled',false).html(original);
        }
    });

    $('#paymentForm').on('submit',async function(e){
        e.preventDefault();
        const form=this;
        if(!form.reportValidity())return;

        const modal=$(form).closest('.sc-modal');
        const button=$(form).find('button[type="submit"]');
        if(button.prop('disabled'))return;

        const original=button.html();
        const paymentKey=String($('#payment_key').val()||'');
        const selectedPlan=$('#new_plan_id_on_payment option:selected').text().trim();
        const selectedCycle=$('#ciclo_pago option:selected').text().trim();
        const amount=String($('#monto_pago').val()||'0');
        const currentEnd=$('#paymentCurrentEnd').text().trim();
        const newEnd=$('#paymentNewEnd').text().trim();

        // El modal se retira completamente de la capa visual antes de abrir
        // SweetAlert. Así ninguna confirmación puede quedar detrás del formulario.
        hardHideModal(modal);
        await wait(80);

        const confirmation=await showTopDialog({
            icon:'question',
            title:'Confirmar renovación',
            html:`<div style="text-align:left;display:grid;gap:9px">
                <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
                    <span style="padding:10px;border:1px solid #e2e8f0;border-radius:10px"><small style="display:block;color:#64748b;font-weight:800">PLAN</small><strong>${escapeHtml(selectedPlan)}</strong></span>
                    <span style="padding:10px;border:1px solid #e2e8f0;border-radius:10px"><small style="display:block;color:#64748b;font-weight:800">MODALIDAD</small><strong>${escapeHtml(selectedCycle)}</strong></span>
                </div>
                <span style="padding:10px;border:1px solid #e2e8f0;border-radius:10px"><small style="display:block;color:#64748b;font-weight:800">MONTO</small><strong>S/ ${escapeHtml(amount)}</strong></span>
                <div style="padding:11px;border-radius:10px;background:#ecfdf5;color:#166534"><strong>${escapeHtml(currentEnd)}</strong> &nbsp;→&nbsp; <strong>${escapeHtml(newEnd)}</strong></div>
            </div>`,
            showCancelButton:true,
            confirmButtonText:'Sí, registrar y renovar',
            cancelButtonText:'Volver al formulario',
            confirmButtonColor:'#16a34a',
            cancelButtonColor:'#64748b',
            reverseButtons:true,
            allowOutsideClick:false
        });

        if(!confirmation.isConfirmed){
            restoreModalLayer(modal);
            openModal(modal);
            return;
        }

        modal.attr('data-busy','1');
        button.prop('disabled',true).html('<i class="fas fa-spinner fa-spin"></i> Registrando renovación…');
        showTopDialog({
            title:'Registrando renovación…',
            text:'Se está guardando el pago y actualizando la nueva vigencia.',
            allowOutsideClick:false,
            allowEscapeKey:false,
            showConfirmButton:false,
            didOpen:()=>Swal.showLoading()
        });

        const postPromise=(async()=>{
            const response=await fetchWithTimeout('ajax/renovar_suscripcion.php',{
                method:'POST',
                body:new FormData(form),
                credentials:'same-origin',
                headers:{'X-Requested-With':'XMLHttpRequest','Accept':'application/json'},
                cache:'no-store'
            },15000);
            return await readJsonResponse(response);
        })();

        const pollPromise=pollRenewalStatus(paymentKey).then(result=>result?{
            success:true,
            duplicate:true,
            message:'El pago fue registrado y la vigencia se actualizó correctamente.',
            ...result
        }:null);

        try{
            const result=await Promise.race([
                postPromise,
                pollPromise.then(value=>value||new Promise(()=>{}))
            ]);
            if(result.referral_job)dispatchReferralJob(result.referral_job);
            Swal.close();
            await showTopDialog({
                icon:'success',
                title:result.duplicate?'Renovación confirmada':'Renovación registrada',
                text:result.message||'El pago y la nueva vigencia fueron registrados.',
                confirmButtonColor:'#16a34a'
            });
            location.reload();
        }catch(firstError){
            let recovered=null;
            try{recovered=await pollPromise}catch(error){}
            Swal.close();
            if(recovered){
                if(recovered.referral_job)dispatchReferralJob(recovered.referral_job);
                const end=recovered.new_end_date?fmt(parseDate(recovered.new_end_date)):'la fecha registrada';
                await showTopDialog({
                    icon:'success',
                    title:'Renovación confirmada',
                    text:`El pago sí fue registrado. La vigencia termina el ${end}.`,
                    confirmButtonColor:'#16a34a'
                });
                location.reload();
                return;
            }

            await showTopDialog({
                icon:'error',
                title:'No se pudo confirmar la renovación',
                text:firstError?.message||'El servidor no confirmó el registro. Revisa el historial de pagos antes de volver a intentarlo.',
                confirmButtonColor:'#dc2626'
            });
            restoreModalLayer(modal);
            openModal(modal);
        }finally{
            modal.removeAttr('data-busy');
            button.prop('disabled',false).html(original);
        }
    });

    async function showWhatsAppPreview(data,template,mode='suscripcion'){
        const message=professionalWhatsAppMessage(data,template,mode);
        const phone=String(data.telefono||'').replace(/\D+/g,'');
        const result=await Swal.fire({
          title:'<span style="display:flex;align-items:center;justify-content:center;gap:9px"><i class="fab fa-whatsapp" style="color:#16a34a"></i> Mensaje de suscripción listo</span>',
          html:`<div style="text-align:left">
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px">
              <span style="padding:9px 11px;border:1px solid #e2e8f0;border-radius:10px;background:#f8fafc"><small style="display:block;color:#64748b;font-weight:800;text-transform:uppercase;font-size:9px">Plantilla</small><strong style="display:block;margin-top:3px;color:#1e293b;font-size:12px">${escapeHtml(template.nombre_plantilla||'Suscripción')}</strong></span>
              <span style="padding:9px 11px;border:1px solid #e2e8f0;border-radius:10px;background:#f8fafc"><small style="display:block;color:#64748b;font-weight:800;text-transform:uppercase;font-size:9px">Destinatario</small><strong style="display:block;margin-top:3px;color:#1e293b;font-size:12px">${escapeHtml(data.nombre_cliente||'Suscriptor')}</strong></span>
            </div>
            ${!phone?'<div style="margin-bottom:10px;padding:10px 12px;border-radius:10px;background:#fff7e3;color:#9a6700"><i class="fas fa-triangle-exclamation"></i> No hay teléfono registrado. Puedes copiar el mensaje y enviarlo manualmente.</div>':''}
            <div style="max-height:340px;overflow:auto;background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:16px;line-height:1.65;color:#1e293b">${previewHtml(message)}</div>
          </div>`,
          showCancelButton:true,showDenyButton:true,showConfirmButton:!!phone,
          confirmButtonText:'<i class="fab fa-whatsapp"></i> Enviar por WhatsApp',
          denyButtonText:'<i class="fas fa-copy"></i> Copiar mensaje',cancelButtonText:'Cancelar',
          confirmButtonColor:'#16a34a',denyButtonColor:'#475569',reverseButtons:true,width:620
        });
        if(result.isConfirmed&&phone)window.open(`https://wa.me/${phone}?text=${encodeURIComponent(message)}`,'_blank','noopener');
        else if(result.isDenied){await copyText(message);Swal.fire({icon:'success',title:'Mensaje copiado',text:'Está listo para pegarse en WhatsApp.',timer:1600,showConfirmButton:false})}
    }
    async function selectMessageTemplate(items, mode='suscripcion'){
        if(!items.length){
            await Swal.fire('Atención', mode==='promocion'?'No hay plantillas de promoción configuradas.':'No hay plantillas configuradas para suscripciones.', 'warning');
            return null;
        }
        const cleanPreview=value=>String(value||'').replace(/\{[^}]+\}/g,'dato').replace(/\*/g,'').replace(/\s+/g,' ').trim();
        const cards=items.map(item=>{
            const raw=cleanPreview(item.mensaje);
            const preview=raw.slice(0,150);
            const label=mode==='promocion'?'Promoción':'Suscripción';
            const icon=mode==='promocion'?'fa-bullhorn':'fa-message';
            const searchText=String(item.nombre_plantilla||'')+' '+raw;
            return `<button type="button" class="af-template-card" data-template-id="${item.id}" data-template-search="${escapeHtml(searchText.toLowerCase())}">
                <span class="af-template-icon"><i class="fas ${icon}"></i></span>
                <span class="af-template-copy"><strong>${escapeHtml(item.nombre_plantilla||'Plantilla')}</strong><span>${escapeHtml(preview||'Mensaje configurado para WhatsApp.')}${raw.length>150?'…':''}</span><small>${label}</small></span>
                <i class="fas fa-circle-check af-template-check"></i>
            </button>`;
        }).join('');
        let selected='';
        const result=await Swal.fire({
            title:'<span style="display:flex;justify-content:center;align-items:center;gap:9px"><i class="fab fa-whatsapp" style="color:#16a34a"></i> Seleccionar plantilla</span>',
            html:`<div class="af-template-picker">
                <div class="af-template-search"><i class="fas fa-search"></i><input id="afTemplateSearch" type="search" placeholder="Buscar por nombre o contenido"></div>
                <div id="afTemplateList" class="af-template-list">${cards}</div>
                <div id="afTemplateEmpty" class="af-template-empty" hidden>No se encontraron plantillas con esa búsqueda.</div>
                <div class="af-template-tip"><i class="fas fa-circle-info"></i><span>Selecciona una plantilla para revisar el mensaje completo antes de copiarlo o enviarlo por WhatsApp.</span></div>
            </div>`,
            width:680,
            showCancelButton:true,
            confirmButtonText:'<i class="fas fa-arrow-right"></i> Revisar mensaje',
            cancelButtonText:'Cancelar',
            confirmButtonColor:'#dc2626',
            focusConfirm:false,
            didOpen:()=>{
                const popup=Swal.getPopup(),confirm=Swal.getConfirmButton(),search=popup.querySelector('#afTemplateSearch');
                confirm.disabled=true;
                popup.querySelectorAll('.af-template-card').forEach(card=>{
                    card.addEventListener('click',()=>{
                        selected=String(card.dataset.templateId||'');
                        popup.querySelectorAll('.af-template-card').forEach(item=>item.classList.toggle('is-selected',item===card));
                        confirm.disabled=!selected;
                    });
                });
                search.addEventListener('input',()=>{
                    const query=search.value.trim().toLowerCase();
                    let visible=0;
                    popup.querySelectorAll('.af-template-card').forEach(card=>{
                        const show=!query||String(card.dataset.templateSearch||'').includes(query);
                        card.hidden=!show;
                        if(show)visible++;
                    });
                    popup.querySelector('#afTemplateEmpty').hidden=visible>0;
                });
                search.focus();
            },
            preConfirm:()=>{
                if(!selected){Swal.showValidationMessage('Selecciona una plantilla.');return false}
                return selected;
            }
        });
        if(!result.isConfirmed||!result.value)return null;
        return items.find(item=>String(item.id)===String(result.value))||null;
    }

    $('#tablaSuscripciones').on('click','.whatsapp-btn',async function(){
        const data=$(this).data();
        const template=await selectMessageTemplate(templates,'suscripcion');
        if(template)showWhatsAppPreview(data,template,'suscripcion');
    });

    $('#tablaSuscripciones').on('click','.promote-btn',async function(){
        const data=$(this).data();
        const template=await selectMessageTemplate(promoTemplates,'promocion');
        if(template)showWhatsAppPreview(data,template,'promocion');
    });

    function postDelete(data){
        return $.ajax({
            url:'gestionar_suscripciones.php',
            method:'POST',
            data:{...data,_csrf:<?= json_encode(Security::csrfToken()) ?>},
            dataType:'json',
            timeout:30000
        });
    }
    $('#tablaSuscripciones').on('click','.delete-subscription-btn',async function(){
        const id=$(this).data('id');
        const confirm=await Swal.fire({
            title:'¿Eliminar suscripción?',
            text:'Se eliminarán también sus pagos y renovaciones asociadas.',
            icon:'warning',
            showCancelButton:true,
            confirmButtonText:'Sí, eliminar',
            cancelButtonText:'Cancelar',
            confirmButtonColor:'#dc2626'
        });
        if(!confirm.isConfirmed)return;
        Swal.fire({title:'Eliminando suscripción…',text:'Espera mientras se eliminan los registros asociados.',allowOutsideClick:false,allowEscapeKey:false,didOpen:()=>Swal.showLoading()});
        try{
            const result=await postDelete({action:'delete_subscription',id_suscripcion:id});
            if(!result.success)throw new Error(result.message||'No se pudo eliminar.');
            await Swal.fire({icon:'success',title:'Suscripción eliminada',text:result.message,confirmButtonColor:'#dc2626'});
            location.reload();
        }catch(error){
            await Swal.fire('No se pudo eliminar',error.responseJSON?.message||error.message||'Ocurrió un error al eliminar la suscripción.','error');
        }
    });
    $('#tablaSuscripciones').on('click','.delete-subscriber-btn',async function(){
        const id=$(this).data('id'),name=String($(this).data('nombre')||'este Admin');
        const confirm=await Swal.fire({
            title:'Eliminar Admin y todos sus datos',
            html:`<div style="text-align:left;line-height:1.55">
                <p>Se eliminará <strong>${escapeHtml(name)}</strong> junto con su suscripción, pagos, monedero, buzones, dominios, cuentas, clientes y demás datos asociados.</p>
                <div style="margin-top:12px;padding:11px 12px;border-radius:10px;background:#fff1f2;color:#9f1239"><strong>Esta acción es irreversible.</strong></div>
                <p style="margin-top:12px;color:#475569;font-size:13px">Confirma únicamente con el botón rojo para continuar.</p>
            </div>`,
            icon:'warning',
            showCancelButton:true,
            confirmButtonText:'Eliminar definitivamente',
            cancelButtonText:'Cancelar',
            confirmButtonColor:'#dc2626',
            focusCancel:true,
            reverseButtons:true
        });
        if(!confirm.isConfirmed)return;
        Swal.fire({title:'Eliminando Admin…',text:'Se están eliminando de forma segura todos los datos asociados.',allowOutsideClick:false,allowEscapeKey:false,didOpen:()=>Swal.showLoading()});
        try{
            const result=await postDelete({action:'delete_subscriber',id_usuario:id});
            if(!result.success)throw new Error(result.message||'No se pudo eliminar.');
            await Swal.fire({icon:'success',title:'Admin eliminado correctamente',text:result.message,confirmButtonColor:'#dc2626'});
            location.reload();
        }catch(error){
            await Swal.fire('No se pudo eliminar',error.responseJSON?.message||error.message||'Ocurrió un error al eliminar el Admin.','error');
        }
    });
});
</script>
<?php require_once __DIR__ . '/admin_footer.php'; ?>
