<?php

declare(strict_types=1);

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

restringir_modulo_superadmin('Buzones');
exigir_permiso('gestionar_propios_buzones', 'No tienes permiso para gestionar buzones.');

$idAdmin = (int) ($_SESSION['admin']['uid'] ?? 0);
$role = (string) ($_SESSION['admin']['rol'] ?? '');

function afenixx_imap_clear_errors(): void
{
    if (function_exists('imap_errors')) {
        @imap_errors();
    }
    if (function_exists('imap_alerts')) {
        @imap_alerts();
    }
}

/**
 * Verifica una cuenta IMAP sin guardar ni exponer la credencial.
 * Devuelve un código estable para distinguir credenciales, certificado y red.
 *
 * @return array{success:bool,message:string,code:string}
 */
function afenixx_imap_verify(
    string $host,
    int $port,
    string $user,
    string $password,
    string $flags,
    string $provider = ''
): array {
    if (!function_exists('imap_open')) {
        return [
            'success' => false,
            'message' => 'La extensión IMAP no está habilitada en el servidor web.',
            'code' => 'extension_missing',
        ];
    }

    $host = strtolower(trim($host));
    $user = strtolower(trim($user));
    $flags = trim($flags) !== '' ? trim($flags) : '/imap/ssl';
    $providerText = strtolower(trim($provider . ' ' . $host));

    if ($host === '' || $port < 1 || $user === '' || $password === '') {
        return [
            'success' => false,
            'message' => 'La configuración IMAP está incompleta.',
            'code' => 'incomplete',
        ];
    }

    if (function_exists('imap_timeout')) {
        @imap_timeout(IMAP_OPENTIMEOUT, 15);
        @imap_timeout(IMAP_READTIMEOUT, 20);
    }

    $attempts = [[$host, $port, $flags]];
    $isGmail = str_contains($providerText, 'gmail') || $host === 'imap.gmail.com';
    $isCpanel = !$isGmail && (
        str_contains($providerText, 'cpanel')
        || str_contains($providerText, 'hosting')
        || str_starts_with($host, 'mail.')
    );

    // Algunos servidores cPanel usan certificados emitidos para el hostname del
    // servidor, no para mail.dominio.com. Este respaldo solo se intenta cuando
    // el primer fallo NO es de autenticación.
    if ($isCpanel && str_contains($flags, '/ssl') && !str_contains($flags, '/novalidate-cert')) {
        $attempts[] = [$host, $port, $flags . '/novalidate-cert'];
    }

    $lastDetail = 'Error desconocido';
    foreach ($attempts as $index => [$attemptHost, $attemptPort, $attemptFlags]) {
        afenixx_imap_clear_errors();
        $mailbox = sprintf('{%s:%d%s}INBOX', $attemptHost, $attemptPort, $attemptFlags);
        $stream = @imap_open($mailbox, $user, $password, OP_HALFOPEN, 1, [
            'DISABLE_AUTHENTICATOR' => 'GSSAPI',
        ]);

        if ($stream !== false) {
            @imap_close($stream);
            afenixx_imap_clear_errors();
            return [
                'success' => true,
                'message' => $index === 0
                    ? 'Conexión correcta. La credencial y el servidor IMAP funcionan.'
                    : 'Conexión correcta usando compatibilidad de certificado para cPanel.',
                'code' => 'ok',
            ];
        }

        $errors = function_exists('imap_errors') ? (@imap_errors() ?: []) : [];
        $lastDetail = trim(implode(' | ', array_filter([
            (string) (imap_last_error() ?: ''),
            ...array_map('strval', is_array($errors) ? $errors : []),
        ]))) ?: 'Error desconocido';

        // Cambiar flags o certificado no corrige una contraseña rechazada.
        if (stripos($lastDetail, 'AUTHENTICATIONFAILED') !== false
            || stripos($lastDetail, 'authentication failed') !== false
            || stripos($lastDetail, 'login failed') !== false
            || stripos($lastDetail, 'invalid credentials') !== false) {
            break;
        }
    }

    error_log(sprintf(
        '[Buzones] Fallo IMAP para %s en %s:%d (%s): %s',
        $user,
        $host,
        $port,
        $provider !== '' ? $provider : 'manual',
        $lastDetail
    ));

    if (stripos($lastDetail, 'AUTHENTICATIONFAILED') !== false
        || stripos($lastDetail, 'authentication failed') !== false
        || stripos($lastDetail, 'login failed') !== false
        || stripos($lastDetail, 'invalid credentials') !== false) {
        return [
            'success' => false,
            'message' => $isGmail
                ? 'Gmail rechazó la credencial. Genera una contraseña de aplicación nueva y vuelve a guardarla; no uses la contraseña normal de Google.'
                : 'El servidor rechazó la contraseña guardada. Edita el buzón y escribe la contraseña actual de esa cuenta de correo en cPanel o en tu proveedor.',
            'code' => 'authentication',
        ];
    }

    if (stripos($lastDetail, 'certificate') !== false
        || stripos($lastDetail, 'self signed') !== false
        || stripos($lastDetail, 'peer certificate') !== false) {
        return [
            'success' => false,
            'message' => 'El servidor respondió, pero su certificado TLS no coincide. Usa el hostname IMAP indicado por tu hosting o consulta el dato exacto en “Configurar cliente de correo” de cPanel.',
            'code' => 'certificate',
        ];
    }

    if (stripos($lastDetail, "Can't connect") !== false
        || stripos($lastDetail, 'timed out') !== false
        || stripos($lastDetail, 'connection refused') !== false
        || stripos($lastDetail, 'name or service not known') !== false) {
        return [
            'success' => false,
            'message' => 'No se pudo alcanzar el servidor IMAP. Revisa host, puerto, SSL y que el hosting permita conexiones salientes.',
            'code' => 'network',
        ];
    }

    return [
        'success' => false,
        'message' => 'No fue posible abrir el buzón. Revisa los datos IMAP indicados por el proveedor y vuelve a probar la conexión.',
        'code' => 'connection',
    ];
}

function afenixx_buzon_limit(PDO $pdo, int $adminId): ?int
{
    $stmt = $pdo->prepare(
        "SELECT p.limite_buzones
         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([$adminId]);
    $value = $stmt->fetchColumn();
    return $value === false || $value === null ? null : (int) $value;
}

if (isset($_GET['fetch_data'])) {
    Security::headers(true);
    $id = filter_input(INPUT_GET, 'fetch_data', FILTER_VALIDATE_INT);
    if (!$id) {
        Security::json(['success' => false, 'message' => 'ID de buzón inválido.'], 422);
    }

    $stmt = $pdo->prepare(
        'SELECT id, imap_host, imap_puerto, imap_usuario, imap_flags, fecha_renovacion,
                nombre_proveedor, plataforma, telefono
         FROM configuraciones_imap
         WHERE id = ? AND id_admin = ? LIMIT 1'
    );
    $stmt->execute([$id, $idAdmin]);
    $data = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$data) {
        Security::json(['success' => false, 'message' => 'El buzón no existe o no te pertenece.'], 404);
    }

    $data['fecha_renovacion'] = !empty($data['fecha_renovacion'])
        ? date('Y-m-d', strtotime((string) $data['fecha_renovacion']))
        : '';
    $data['imap_clave'] = '';
    $data['legacy_outlook'] = ImapProviderCatalog::isMicrosoftProvider(
        (string) ($data['plataforma'] ?? $data['nombre_proveedor'] ?? ''),
        (string) ($data['imap_host'] ?? '')
    );

    Security::json(['success' => true, 'data' => $data]);
}

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

    if ($action === 'delete_buzon') {
        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            Security::json(['success' => false, 'message' => 'ID de buzón inválido.'], 422);
        }

        $usage = $pdo->prepare(
            'SELECT COUNT(*) FROM dominios WHERE id_buzon_entrada = ? AND id_admin_propietario = ?'
        );
        $usage->execute([$id, $idAdmin]);
        if ((int) $usage->fetchColumn() > 0) {
            Security::json([
                'success' => false,
                'message' => 'No se puede eliminar porque el buzón está asignado a uno o más dominios.',
            ], 409);
        }

        $delete = $pdo->prepare('DELETE FROM configuraciones_imap WHERE id = ? AND id_admin = ?');
        $delete->execute([$id, $idAdmin]);
        if ($delete->rowCount() !== 1) {
            Security::json(['success' => false, 'message' => 'El buzón no fue encontrado.'], 404);
        }
        Security::json(['success' => true, 'message' => 'Buzón eliminado correctamente.']);
    }

    if ($action === 'test_buzon') {
        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
        if (!$id) {
            Security::json(['success' => false, 'message' => 'ID de buzón inválido.'], 422);
        }

        $stmt = $pdo->prepare('SELECT * FROM configuraciones_imap WHERE id = ? AND id_admin = ? LIMIT 1');
        $stmt->execute([$id, $idAdmin]);
        $mailbox = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$mailbox) {
            Security::json(['success' => false, 'message' => 'El buzón no existe o no te pertenece.'], 404);
        }

        try {
            $plainPassword = CryptoService::decryptOrFail((string) ($mailbox['imap_clave'] ?? ''));
        } catch (Throwable $e) {
            Security::json([
                'success' => false,
                'message' => 'La credencial guardada no puede recuperarse. Edita el buzón y escribe nuevamente la contraseña.',
                'code' => 'decrypt',
            ], 409);
        }

        $verification = afenixx_imap_verify(
            (string) ($mailbox['imap_host'] ?? ''),
            (int) ($mailbox['imap_puerto'] ?? 993),
            (string) ($mailbox['imap_usuario'] ?? ''),
            $plainPassword,
            (string) ($mailbox['imap_flags'] ?? '/imap/ssl'),
            (string) ($mailbox['plataforma'] ?? $mailbox['nombre_proveedor'] ?? '')
        );

        Security::json($verification, $verification['success'] ? 200 : 409);
    }

    if ($action !== 'guardar_buzon' && !isset($_POST['guardar_buzon'])) {
        Security::json(['success' => false, 'message' => 'Acción no reconocida.'], 400);
    }

    try {
        $id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT) ?: null;
        $account = strtolower(trim((string) ($_POST['cuenta'] ?? '')));
        $password = (string) ($_POST['password'] ?? '');
        $providerSelection = trim((string) ($_POST['proveedor_plataforma'] ?? ''));
        $manualProvider = trim((string) ($_POST['nombre_proveedor_manual'] ?? ''));
        if ($providerSelection === 'Otra' && $manualProvider === '') {
            $manualProvider = 'cPanel / Otro IMAP compatible';
        }
        $manualHost = trim((string) ($_POST['imap_host'] ?? ''));
        $manualPort = filter_input(INPUT_POST, 'imap_puerto', FILTER_VALIDATE_INT) ?: 0;
        $manualFlags = trim((string) ($_POST['imap_flags'] ?? ''));
        $renewalDate = trim((string) ($_POST['fecha_renovacion'] ?? ''));
        $phone = trim((string) ($_POST['telefono'] ?? ''));

        if (!filter_var($account, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException('Ingresa una cuenta de correo válida.');
        }
        if (!in_array($providerSelection, ['Gmail', 'Namecheap Private Email', 'Otra'], true)) {
            throw new InvalidArgumentException('Solo se permiten Gmail, Namecheap Private Email y correo de dominio/cPanel u otro IMAP compatible.');
        }
        $date = DateTimeImmutable::createFromFormat('!Y-m-d', $renewalDate);
        if (!$date || $date->format('Y-m-d') !== $renewalDate) {
            throw new InvalidArgumentException('La fecha de renovación no es válida.');
        }
        if (strlen($phone) > 20) {
            throw new InvalidArgumentException('El teléfono supera la longitud permitida.');
        }

        $resolved = ImapProviderCatalog::resolve(
            $providerSelection,
            $manualProvider,
            $manualHost,
            $manualPort,
            $manualFlags
        );

        $existing = null;
        if ($id !== null) {
            $stmt = $pdo->prepare('SELECT * FROM configuraciones_imap WHERE id = ? AND id_admin = ? LIMIT 1');
            $stmt->execute([$id, $idAdmin]);
            $existing = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$existing) {
                throw new RuntimeException('El buzón no existe o no te pertenece.');
            }
        } else {
            $limit = in_array($role, ['Admin', 'Ayudante de Superadmin'], true) ? afenixx_buzon_limit($pdo, $idAdmin) : null;
            if ($limit !== null) {
                $count = $pdo->prepare('SELECT COUNT(*) FROM configuraciones_imap WHERE id_admin = ?');
                $count->execute([$idAdmin]);
                if ((int) $count->fetchColumn() >= $limit) {
                    throw new RuntimeException('Alcanzaste el límite de buzones permitido por tu plan.');
                }
            }
        }

        $duplicateSql = 'SELECT COUNT(*) FROM configuraciones_imap WHERE id_admin = ? AND imap_usuario = ?';
        $duplicateParams = [$idAdmin, $account];
        if ($id !== null) {
            $duplicateSql .= ' AND id <> ?';
            $duplicateParams[] = $id;
        }
        $duplicate = $pdo->prepare($duplicateSql);
        $duplicate->execute($duplicateParams);
        if ((int) $duplicate->fetchColumn() > 0) {
            throw new RuntimeException('Ya existe un buzón con esa cuenta de correo.');
        }

        if ($password !== '') {
            $verification = afenixx_imap_verify(
                $resolved['host'],
                $resolved['port'],
                $account,
                $password,
                $resolved['flags'],
                $providerSelection
            );
            if (!$verification['success']) {
                throw new RuntimeException($verification['message']);
            }
            $encryptedPassword = CryptoService::encrypt($password);
        } elseif ($existing) {
            $encryptedPassword = (string) $existing['imap_clave'];
            $plain = CryptoService::decrypt($encryptedPassword);
            if ($plain === null || $plain === '') {
                throw new RuntimeException('La credencial guardada no puede recuperarse. Escribe nuevamente la contraseña del buzón.');
            }

            // No permitir que una edición aparentemente correcta conserve una
            // contraseña vencida o cambiada en Gmail/cPanel.
            $verification = afenixx_imap_verify(
                $resolved['host'],
                $resolved['port'],
                $account,
                $plain,
                $resolved['flags'],
                $providerSelection
            );
            if (!$verification['success']) {
                throw new RuntimeException($verification['message'] . ' Escribe la nueva contraseña en el formulario para repararlo.');
            }

            if (CryptoService::needsMigration($encryptedPassword)) {
                $encryptedPassword = CryptoService::encrypt($plain);
            }
        } else {
            throw new InvalidArgumentException('La contraseña es obligatoria para un buzón nuevo.');
        }

        $platformValue = isset(ImapProviderCatalog::providers()[$providerSelection])
            ? $providerSelection
            : 'Otra';

        $pdo->beginTransaction();
        if ($id !== null) {
            $stmt = $pdo->prepare(
                'UPDATE configuraciones_imap
                 SET imap_usuario = ?, imap_clave = ?, nombre_proveedor = ?, plataforma = ?,
                     imap_host = ?, imap_puerto = ?, imap_flags = ?, fecha_renovacion = ?, telefono = ?
                 WHERE id = ? AND id_admin = ?'
            );
            $stmt->execute([
                $account,
                $encryptedPassword,
                $resolved['provider'],
                $platformValue,
                $resolved['host'],
                $resolved['port'],
                $resolved['flags'],
                $renewalDate,
                $phone !== '' ? $phone : null,
                $id,
                $idAdmin,
            ]);
            $message = 'Buzón actualizado correctamente.';
        } else {
            $stmt = $pdo->prepare(
                'INSERT INTO configuraciones_imap
                 (imap_usuario, imap_clave, nombre_proveedor, plataforma, imap_host, imap_puerto,
                  imap_flags, fecha_renovacion, telefono, id_admin, fecha_creacion)
                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())'
            );
            $stmt->execute([
                $account,
                $encryptedPassword,
                $resolved['provider'],
                $platformValue,
                $resolved['host'],
                $resolved['port'],
                $resolved['flags'],
                $renewalDate,
                $phone !== '' ? $phone : null,
                $idAdmin,
            ]);
            $message = 'Buzón creado correctamente.';
        }
        $pdo->commit();

        Security::json(['success' => true, 'message' => $message]);
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        error_log('Error gestionando buzón: ' . $e->getMessage());
        $isExpected = $e instanceof InvalidArgumentException || $e instanceof RuntimeException;
        $status = $e instanceof InvalidArgumentException ? 422 : 400;
        Security::json(['success' => false, 'message' => $isExpected ? $e->getMessage() : 'No se pudo completar la operación del buzón.'], $status);
    }
}

$titulo_pagina = 'Gestionar Buzones de Entrada';
$limit = in_array($role, ['Admin', 'Ayudante de Superadmin'], true) ? afenixx_buzon_limit($pdo, $idAdmin) : null;
$countStmt = $pdo->prepare('SELECT COUNT(*) FROM configuraciones_imap WHERE id_admin = ?');
$countStmt->execute([$idAdmin]);
$currentCount = (int) $countStmt->fetchColumn();
$limitReached = $limit !== null && $currentCount >= $limit;

$listStmt = $pdo->prepare('SELECT * FROM configuraciones_imap WHERE id_admin = ? ORDER BY imap_usuario ASC');
$listStmt->execute([$idAdmin]);
$mailboxes = $listStmt->fetchAll(PDO::FETCH_ASSOC);
$legacyCount = 0;
foreach ($mailboxes as &$mailbox) {
    $mailbox['legacy_outlook'] = ImapProviderCatalog::isMicrosoftProvider(
        (string) ($mailbox['plataforma'] ?? $mailbox['nombre_proveedor'] ?? ''),
        (string) ($mailbox['imap_host'] ?? '')
    );
    $mailboxHost = strtolower(trim((string) ($mailbox['imap_host'] ?? '')));
    $mailboxPlatform = trim((string) ($mailbox['plataforma'] ?? $mailbox['nombre_proveedor'] ?? ''));
    if ($mailbox['legacy_outlook']) {
        $mailbox['provider_key'] = 'legacy';
        $legacyCount++;
    } elseif ($mailboxPlatform === 'Gmail' || $mailboxHost === 'imap.gmail.com') {
        $mailbox['provider_key'] = 'Gmail';
    } elseif ($mailboxPlatform === 'Namecheap Private Email' || $mailboxHost === 'mail.privateemail.com') {
        $mailbox['provider_key'] = 'Namecheap Private Email';
    } else {
        $mailbox['provider_key'] = 'Otra';
    }
}
unset($mailbox);

// Para nuevos registros se habilitan Gmail, Namecheap Private Email y correo de dominio/cPanel u otro IMAP compatible.
$providers = ['Gmail', 'Namecheap Private Email', 'Otra'];
$configs = [];
foreach (['Gmail', 'Namecheap Private Email'] as $automaticProvider) {
    $catalogEntry = ImapProviderCatalog::providers()[$automaticProvider] ?? null;
    if (is_array($catalogEntry)) {
        $configs[$automaticProvider] = [
            'host' => $catalogEntry['host'],
            'puerto' => $catalogEntry['port'],
            'flags' => $catalogEntry['flags'],
            'message' => $catalogEntry['message'],
        ];
    }
}

$compatibleCount = max(0, $currentCount - $legacyCount);
$dueSoonCount = 0;
foreach ($mailboxes as $mailboxRow) {
    if (empty($mailboxRow['fecha_renovacion'])) { continue; }
    $days = (int) floor((strtotime((string) $mailboxRow['fecha_renovacion']) - strtotime(date('Y-m-d'))) / 86400);
    if ($days >= 0 && $days <= 30) { $dueSoonCount++; }
}

require_once __DIR__ . '/admin_header.php';
?>
<div class="af-page">
    <header class="af-heading">
        <div class="af-heading-main">
            <span class="af-heading-icon"><i class="fas fa-inbox"></i></span>
            <div>
                <p class="af-eyebrow">Configuración de correo</p>
                <h1>Buzones de entrada</h1>
                <p>Conecta buzones de Gmail, Namecheap Private Email o correos de dominio/cPanel y otros servidores IMAP compatibles.</p>
            </div>
        </div>
        <div class="af-heading-actions">
            <button type="button" id="openMailboxModal" class="af-btn af-btn-primary" <?= $limitReached ? 'disabled' : '' ?>>
                <i class="fas fa-plus"></i> Nuevo buzón
            </button>
        </div>
    </header>

    <?php if ($limitReached): ?>
        <div class="af-alert af-alert-warning"><i class="fas fa-triangle-exclamation"></i><div>Alcanzaste el límite de <strong><?= number_format($currentCount) ?>/<?= number_format((int) $limit) ?></strong> buzones permitido por tu plan.</div></div>
    <?php endif; ?>
    <?php if ($legacyCount > 0): ?>
        <div class="af-alert af-alert-danger"><i class="fas fa-circle-exclamation"></i><div><strong><?= number_format($legacyCount) ?> registro(s) heredado(s) de Microsoft.</strong> Deben migrarse a Gmail, Namecheap Private Email o a un correo corporativo compatible. No se eliminan automáticamente.</div></div>
    <?php endif; ?>

    <section class="af-stats" aria-label="Resumen de buzones">
        <article class="af-stat"><span class="af-stat-icon"><i class="fas fa-inbox"></i></span><div><p class="af-stat-label">Buzones registrados</p><p class="af-stat-value"><?= number_format($currentCount) ?></p><div class="af-stat-note">Límite: <?= $limit === null ? 'Ilimitado' : number_format($limit) ?></div></div></article>
        <article class="af-stat"><span class="af-stat-icon"><i class="fas fa-circle-check"></i></span><div><p class="af-stat-label">Configurados</p><p class="af-stat-value"><?= number_format($compatibleCount) ?></p><div class="af-stat-note">Usa Probar para validar acceso</div></div></article>
        <article class="af-stat"><span class="af-stat-icon"><i class="fas fa-calendar-day"></i></span><div><p class="af-stat-label">Renuevan en 30 días</p><p class="af-stat-value"><?= number_format($dueSoonCount) ?></p><div class="af-stat-note">Requieren seguimiento</div></div></article>
        <article class="af-stat"><span class="af-stat-icon"><i class="fas fa-ban"></i></span><div><p class="af-stat-label">Por migrar</p><p class="af-stat-value"><?= number_format($legacyCount) ?></p><div class="af-stat-note">Microsoft retirado</div></div></article>
    </section>

    <section class="af-panel">
        <div class="af-panel-head">
            <div class="af-panel-title"><span class="af-panel-title-icon"><i class="fas fa-list"></i></span><div><h2>Registros de buzones</h2><p>Busca por correo o proveedor y filtra el estado de compatibilidad.</p></div></div>
        </div>
        <div class="af-toolbar compact-3">
            <div class="af-field"><label class="af-label" for="mailboxSearch"><i class="fas fa-search"></i> Buscar</label><input id="mailboxSearch" type="search" class="af-control" placeholder="Correo, proveedor o teléfono"></div>
            <div class="af-field"><label class="af-label" for="mailboxProvider"><i class="fas fa-server"></i> Proveedor</label><select id="mailboxProvider" class="af-control"><option value="">Todos</option><option value="Gmail">Gmail</option><option value="Namecheap Private Email">Namecheap Private Email</option><option value="Otra">Correo de dominio / cPanel u otro IMAP</option><option value="legacy">Registro heredado de Microsoft</option></select></div>
            <div class="af-field"><label class="af-label" for="mailboxPerPage"><i class="fas fa-list-ol"></i> Mostrar</label><select id="mailboxPerPage" class="af-control"><option value="100">100 registros</option><option value="200">200 registros</option><option value="400">400 registros</option><option value="all">Todos</option></select></div>
            <div class="af-toolbar-actions"><button type="button" id="clearMailboxFilters" class="af-btn af-btn-secondary"><i class="fas fa-eraser"></i> Limpiar</button></div>
        </div>
        <div class="af-list-meta"><span><?= number_format(count($mailboxes)) ?> buzones registrados</span><span id="mailboxPageSummary"></span></div>
        <div class="af-table-wrap">
            <table id="mailboxTable" class="af-table">
                <thead><tr><th>Cuenta</th><th>Proveedor</th><th>Teléfono</th><th>Renovación</th><th>Estado</th><th>Acciones</th></tr></thead>
                <tbody>
                <?php foreach ($mailboxes as $mailbox):
                    $providerKey = (string) ($mailbox['provider_key'] ?? 'Otra');
                    $renewal = !empty($mailbox['fecha_renovacion']) ? strtotime((string) $mailbox['fecha_renovacion']) : null;
                    $expired = $renewal !== null && $renewal < strtotime(date('Y-m-d'));
                ?>
                    <tr data-af-row data-provider="<?= htmlspecialchars($providerKey, ENT_QUOTES, 'UTF-8') ?>" data-search="<?= htmlspecialchars(($mailbox['imap_usuario'] ?? '') . ' ' . ($mailbox['nombre_proveedor'] ?? '') . ' ' . ($mailbox['telefono'] ?? ''), ENT_QUOTES, 'UTF-8') ?>">
                        <td><span class="af-row-title"><?= htmlspecialchars((string) $mailbox['imap_usuario']) ?></span><span class="af-row-sub"><?= htmlspecialchars((string) ($mailbox['imap_host'] ?? '')) ?>:<?= (int) ($mailbox['imap_puerto'] ?? 0) ?></span></td>
                        <td><?= htmlspecialchars((string) ($mailbox['nombre_proveedor'] ?? 'Manual')) ?></td>
                        <td><?= htmlspecialchars((string) ($mailbox['telefono'] ?: '—')) ?></td>
                        <td><span class="<?= $expired ? 'text-red-700 font-bold' : '' ?>"><?= $renewal ? date('d/m/Y', $renewal) : '—' ?></span></td>
                        <td><?php if ($mailbox['legacy_outlook']): ?><span class="af-badge af-badge-danger"><i class="fas fa-ban"></i> Migrar</span><?php else: ?><span class="af-badge af-badge-neutral"><i class="fas fa-gear"></i> Configurado</span><?php endif; ?></td>
                        <td><div class="af-actions"><button type="button" class="af-btn af-btn-secondary af-btn-icon js-test-mailbox" data-id="<?= (int) $mailbox['id'] ?>" data-account="<?= htmlspecialchars((string) $mailbox['imap_usuario'], ENT_QUOTES, 'UTF-8') ?>" title="Probar conexión"><i class="fas fa-plug-circle-check"></i></button><button type="button" class="af-btn af-btn-secondary af-btn-icon js-edit-mailbox" data-id="<?= (int) $mailbox['id'] ?>" title="Editar"><i class="fas fa-pen"></i></button><button type="button" class="af-btn af-btn-danger af-btn-icon js-delete-mailbox" data-id="<?= (int) $mailbox['id'] ?>" data-account="<?= htmlspecialchars((string) $mailbox['imap_usuario'], ENT_QUOTES, 'UTF-8') ?>" title="Eliminar"><i class="fas fa-trash"></i></button></div></td>
                    </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
            <div id="mailboxEmpty" class="af-empty" hidden><i class="fas fa-inbox"></i><strong>No se encontraron buzones</strong><div>Modifica los filtros o registra un buzón nuevo.</div></div>
        </div>
        <div class="af-pagination-bar"><span class="af-pagination-summary">“Configurado” no garantiza acceso: usa el botón Probar conexión antes de asignar el buzón a dominios.</span><div id="mailboxPagination" class="af-pagination"></div></div>
    </section>
</div>

<style>
/* Ajuste puntual: alinea Puerto IMAP y Seguridad / Flags dentro del modal de buzones. */
#mailboxModal .af-mailbox-server-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    align-items: start;
    column-gap: 12px;
    row-gap: 10px;
}
#mailboxModal .af-mailbox-server-grid > .full {
    grid-column: 1 / -1 !important;
}
#mailboxModal .af-mailbox-server-grid > div:not(.full) {
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-self: stretch;
}
#mailboxModal .af-mailbox-server-grid > div:not(.full) > .af-label {
    min-height: 20px;
    margin-bottom: 6px;
    display: flex;
    align-items: center;
    line-height: 1.25;
}
#mailboxModal .af-mailbox-server-grid > div:not(.full) > .af-control {
    width: 100%;
}
#mailboxModal .af-mailbox-server-grid > div:not(.full) > .af-help {
    min-height: 28px;
}
@media (max-width: 680px) {
    #mailboxModal .af-mailbox-server-grid {
        grid-template-columns: 1fr !important;
    }
    #mailboxModal .af-mailbox-server-grid > .full {
        grid-column: auto !important;
    }
    #mailboxModal .af-mailbox-server-grid > div:not(.full) > .af-label,
    #mailboxModal .af-mailbox-server-grid > div:not(.full) > .af-help {
        min-height: auto;
    }
}
</style>

<div id="mailboxModal" class="af-modal-backdrop" aria-hidden="true">
    <section class="af-modal af-mailbox-modal" role="dialog" aria-modal="true" aria-labelledby="mailboxModalTitle">
        <header class="af-modal-head">
            <div class="af-modal-title"><span class="af-modal-icon"><i class="fas fa-inbox"></i></span><div><h2 id="mailboxModalTitle">Nuevo buzón</h2><p id="mailboxModalDescription">Conecta Gmail, Namecheap Private Email o un correo de dominio/cPanel u otro IMAP compatible.</p></div></div>
            <button type="button" class="af-modal-close" data-af-close aria-label="Cerrar"><i class="fas fa-xmark"></i></button>
        </header>
        <form id="mailboxForm" autocomplete="off">
            <?= Security::csrfField() ?>
            <input type="hidden" name="action" value="guardar_buzon">
            <input type="hidden" name="id" id="mailboxId">
            <input type="hidden" name="nombre_proveedor_manual" id="mailboxProviderName" value="cPanel / Otro IMAP compatible">
            <div class="af-modal-body">
                <div class="af-guide af-mailbox-security-guide"><i class="fas fa-shield-halved"></i><div><strong>Conexión segura por IMAP.</strong><span>Las credenciales se cifran antes de guardarse. Selecciona el servicio donde está alojado el buzón.</span></div></div>

                <div class="af-field">
                    <label class="af-label" for="mailboxProviderSelect"><i class="fas fa-server"></i> Tipo de buzón *</label>
                    <select id="mailboxProviderSelect" name="proveedor_plataforma" class="af-control" required>
                        <option value="">Seleccionar tipo de buzón</option>
                        <option value="Gmail">Gmail</option>
                        <option value="Namecheap Private Email">Namecheap Private Email</option>
                        <option value="Otra">Correo de dominio / cPanel u otro IMAP</option>
                    </select>
                    <span class="af-help">Selecciona Namecheap solo cuando el buzón pertenezca a Private Email. Para cPanel, hosting o cualquier proveedor IMAP compatible, utiliza Correo de dominio / cPanel u otro IMAP.</span>
                </div>

                <div class="af-form-grid af-mailbox-credentials">
                    <div class="full"><label class="af-label" for="mailboxAccount"><i class="fas fa-envelope"></i> Cuenta de correo *</label><input id="mailboxAccount" name="cuenta" type="email" class="af-control" required autocomplete="username" placeholder="correo@dominio.com" data-clear-placeholder><span class="af-help">Escribe la dirección completa del buzón.</span></div>
                    <div class="full"><label class="af-label" for="mailboxPassword"><i class="fas fa-key"></i> Contraseña *</label><input id="mailboxPassword" name="password" type="password" class="af-control" autocomplete="new-password" placeholder="Contraseña de aplicación o clave del buzón" data-clear-placeholder><span class="af-help" id="mailboxPasswordHelp">Obligatoria al crear. Al editar puedes dejarla vacía, pero el sistema volverá a probar la credencial guardada. Si fue cambiada o venció, deberás escribir la nueva.</span></div>
                </div>

                <div class="af-mailbox-guides">
                <div id="gmailPasswordGuide" class="af-alert af-alert-warning af-mailbox-provider-guide" hidden>
                    <i class="fab fa-google"></i>
                    <div><strong>Gmail requiere una contraseña de aplicación.</strong><br>No uses la contraseña normal de Google.
                        <div class="af-provider-guide-links">
                            <a class="af-btn af-btn-primary" href="https://myaccount.google.com/apppasswords" target="_blank" rel="noopener"><i class="fas fa-key"></i> Crear contraseña</a>
                            <a class="af-btn af-btn-secondary" href="https://support.google.com/accounts/answer/185833?hl=es-419" target="_blank" rel="noopener"><i class="fas fa-book-open"></i> Ver guía</a>
                        </div>
                    </div>
                </div>

                <div id="namecheapGuide" class="af-alert af-alert-info af-mailbox-provider-guide" hidden>
                    <i class="fas fa-envelope-open-text"></i>
                    <div><strong>Namecheap Private Email.</strong><br>Usa el correo completo y la contraseña del buzón. El servidor se configurará automáticamente como <code>mail.privateemail.com</code>.</div>
                </div>

                <div id="cpanelGuide" class="af-alert af-alert-info af-mailbox-provider-guide" hidden>
                    <i class="fas fa-globe"></i>
                    <div><strong>Correo de dominio / cPanel u otro IMAP.</strong><br>Se precargan el puerto <code>993</code> y los flags <code>/imap/ssl</code>. Puedes editar host, puerto y flags cuando tu proveedor use parámetros diferentes.</div>
                </div>
                </div>

                <div id="mailboxProviderMessage" class="af-alert af-alert-info" hidden></div>

                <div id="mailboxServerConfig" class="af-provider-preset">
                    <div class="af-provider-preset-head"><div><h3 class="af-form-section-title">Datos IMAP</h3><p class="af-help">Gmail y Namecheap quedan bloqueados con sus parámetros oficiales. En cPanel u otro IMAP se precargan valores seguros, pero host, puerto y flags son editables.</p></div><span class="af-badge af-badge-neutral"><i class="fas fa-lock"></i> SSL</span></div>
                    <div class="af-form-grid af-mailbox-server-grid">
                        <div class="full"><label class="af-label" for="mailboxHost"><i class="fas fa-network-wired"></i> Host IMAP *</label><input id="mailboxHost" name="imap_host" class="af-control" placeholder="mail.tudominio.com" readonly></div>
                        <div><label class="af-label" for="mailboxPort"><i class="fas fa-plug"></i> Puerto IMAP *</label><input id="mailboxPort" name="imap_puerto" type="number" min="1" max="65535" class="af-control" value="993" readonly><span class="af-help">Recomendado: 993 para IMAP seguro.</span></div>
                        <div><label class="af-label" for="mailboxFlags"><i class="fas fa-shield-halved"></i> Seguridad / Flags *</label><input id="mailboxFlags" name="imap_flags" class="af-control" value="/imap/ssl" readonly><span class="af-help">Recomendado: /imap/ssl. Modifícalo solo si tu proveedor indica otro valor.</span></div>
                    </div>
                </div>

                <div class="af-form-grid af-mailbox-meta">
                    <div><label class="af-label" for="mailboxRenewal"><i class="fas fa-calendar"></i> Renovación *</label><input id="mailboxRenewal" name="fecha_renovacion" type="date" class="af-control" required><span class="af-help">Fecha de control del servicio de correo.</span></div>
                    <div><label class="af-label" for="mailboxPhone"><i class="fab fa-whatsapp"></i> Teléfono</label><input id="mailboxPhone" name="telefono" class="af-control" maxlength="20" placeholder="51999999999" data-clear-placeholder><span class="af-help">Opcional, con código de país.</span></div>
                </div>
            </div>
            <footer class="af-modal-footer"><button type="button" class="af-btn af-btn-secondary" data-af-close>Cancelar</button><button type="submit" class="af-btn af-btn-primary"><i class="fas fa-floppy-disk"></i> Guardar buzón</button></footer>
        </form>
    </section>
</div>

<script>
document.addEventListener('DOMContentLoaded', () => {
    const list = new AfenixAdmin.UnifiedList({table:'#mailboxTable',search:'#mailboxSearch',perPage:'#mailboxPerPage',filters:[{selector:'#mailboxProvider',data:'provider'}],summary:'#mailboxPageSummary',pagination:'#mailboxPagination',empty:'#mailboxEmpty'});
    document.getElementById('clearMailboxFilters').addEventListener('click', () => { document.getElementById('mailboxSearch').value=''; document.getElementById('mailboxProvider').value=''; document.getElementById('mailboxPerPage').value='100'; list.currentPage=1; list.render(); });

    const modal = new AfenixAdmin.ModalController('#mailboxModal');
    const form = document.getElementById('mailboxForm');
    const configs = <?= json_encode($configs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    const csrf = <?= json_encode(Security::csrfToken()) ?>;
    const provider = document.getElementById('mailboxProviderSelect');
    const providerName = document.getElementById('mailboxProviderName');
    const providerMessage = document.getElementById('mailboxProviderMessage');
    const gmailGuide = document.getElementById('gmailPasswordGuide');
    const namecheapGuide = document.getElementById('namecheapGuide');
    const cpanelGuide = document.getElementById('cpanelGuide');
    const accountField = document.getElementById('mailboxAccount');
    const serverConfig = document.getElementById('mailboxServerConfig');
    const hostField = document.getElementById('mailboxHost');
    const portField = document.getElementById('mailboxPort');
    const flagsField = document.getElementById('mailboxFlags');

    function suggestedCpanelHost() {
        const account = String(accountField.value || '').trim().toLowerCase();
        const at = account.lastIndexOf('@');
        return at > 0 && at < account.length - 1 ? `mail.${account.slice(at + 1)}` : '';
    }

    function configureProvider(value, preserveManualValues = false) {
        const config = configs[value] || null;
        const isCpanel = value === 'Otra';
        const isGmail = value === 'Gmail';
        const isNamecheap = value === 'Namecheap Private Email';
        const isAutomatic = isGmail || isNamecheap;

        gmailGuide.hidden = !isGmail;
        namecheapGuide.hidden = !isNamecheap;
        cpanelGuide.hidden = !isCpanel;
        providerName.value = isCpanel ? 'cPanel / Otro IMAP compatible' : (isNamecheap ? 'Namecheap Private Email' : 'Gmail');
        serverConfig.classList.toggle('is-automatic', isAutomatic);

        hostField.readOnly = !isCpanel;
        portField.readOnly = !isCpanel;
        flagsField.readOnly = !isCpanel;
        hostField.required = isCpanel;
        portField.required = value !== '';
        flagsField.required = value !== '';

        if (isAutomatic && config) {
            hostField.value = config.host || (isNamecheap ? 'mail.privateemail.com' : 'imap.gmail.com');
            portField.value = config.puerto || 993;
            flagsField.value = config.flags || '/imap/ssl';
            providerMessage.hidden = false;
            providerMessage.innerHTML = `<i class="fas fa-circle-info"></i><div><strong>Configuración automática:</strong> ${config.host}:${config.puerto} ${config.flags}</div>`;
            return;
        }

        providerMessage.hidden = true;
        providerMessage.innerHTML = '';

        if (isCpanel) {
            if (!preserveManualValues || !hostField.value) {
                hostField.value = suggestedCpanelHost();
            }
            if (!preserveManualValues || !String(portField.value || '').trim()) {
                portField.value = '993';
            }
            if (!preserveManualValues || !String(flagsField.value || '').trim()) {
                flagsField.value = '/imap/ssl';
            }
            return;
        }

        hostField.value = '';
        portField.value = '993';
        flagsField.value = '/imap/ssl';
    }
    provider.addEventListener('change', () => configureProvider(provider.value));
    accountField.addEventListener('blur', () => {
        if (provider.value === 'Otra' && !hostField.value.trim()) {
            hostField.value = suggestedCpanelHost();
        }
    });

    function resetForm(data=null) {
        form.reset();
        document.getElementById('mailboxId').value='';
        provider.value='';
        configureProvider('');
        document.getElementById('mailboxModalTitle').textContent = data ? 'Editar buzón' : 'Nuevo buzón';
        document.getElementById('mailboxModalDescription').textContent = data ? 'Actualiza los datos del buzón seleccionado.' : 'Conecta Gmail, Namecheap Private Email o un correo de dominio/cPanel u otro IMAP compatible.';
        document.getElementById('mailboxPassword').required = !data;
        if (!data) return;
        document.getElementById('mailboxId').value=data.id;
        document.getElementById('mailboxAccount').value=data.imap_usuario||'';
        document.getElementById('mailboxRenewal').value=data.fecha_renovacion||'';
        document.getElementById('mailboxPhone').value=data.telefono||'';
        const currentHost = String(data.imap_host || '').toLowerCase();
        const currentPlatform = String(data.plataforma || data.nombre_proveedor || '');
        const selected = currentPlatform === 'Gmail' || currentHost === 'imap.gmail.com'
            ? 'Gmail'
            : (currentPlatform === 'Namecheap Private Email' || currentHost === 'mail.privateemail.com'
                ? 'Namecheap Private Email'
                : 'Otra');
        provider.value = selected;
        hostField.value = data.imap_host || '';
        portField.value = data.imap_puerto || 993;
        flagsField.value = data.imap_flags || '/imap/ssl';
        providerName.value = selected === 'Gmail' ? 'Gmail' : (selected === 'Namecheap Private Email' ? 'Namecheap Private Email' : (data.nombre_proveedor || 'cPanel / Otro IMAP compatible'));
        configureProvider(selected, true);
        if (data.legacy_outlook) {
            document.getElementById('mailboxPassword').required = true;
        }
    }

    document.getElementById('openMailboxModal').addEventListener('click', function(){ resetForm(); modal.open(this); });
    document.getElementById('mailboxTable').addEventListener('click', async (event) => {
        const test = event.target.closest('.js-test-mailbox');
        const edit = event.target.closest('.js-edit-mailbox');
        const del = event.target.closest('.js-delete-mailbox');
        if (test) {
            try {
                Swal.fire({title:'Probando conexión IMAP...',text:test.dataset.account||'',allowOutsideClick:false,didOpen:()=>Swal.showLoading()});
                const body = new URLSearchParams({action:'test_buzon',id:test.dataset.id,_csrf:csrf});
                const data = await AfenixAdmin.request('gestionar_buzones.php',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body});
                await Swal.fire('Conexión correcta',data.message,'success');
            } catch(e) {
                const result = await Swal.fire({title:'El buzón no conecta',text:e.message,icon:'error',showCancelButton:true,confirmButtonText:'Editar buzón',cancelButtonText:'Cerrar'});
                if (result.isConfirmed) {
                    try { const data=await AfenixAdmin.request(`gestionar_buzones.php?fetch_data=${encodeURIComponent(test.dataset.id)}`); resetForm(data.data); modal.open(test); } catch(fetchError){ Swal.fire('Error',fetchError.message,'error'); }
                }
            }
        }
        if (edit) { try { const data=await AfenixAdmin.request(`gestionar_buzones.php?fetch_data=${encodeURIComponent(edit.dataset.id)}`); resetForm(data.data); modal.open(edit); } catch(e){ Swal.fire('Error',e.message,'error'); } }
        if (del) { const result=await Swal.fire({title:'¿Eliminar buzón?',html:`Se eliminará <strong>${del.dataset.account}</strong>.`,text:'No podrá eliminarse si está asignado a un dominio.',icon:'warning',showCancelButton:true,confirmButtonText:'Sí, eliminar',cancelButtonText:'Cancelar',confirmButtonColor:'#dc2626'}); if(!result.isConfirmed)return; try{const body=new URLSearchParams({action:'delete_buzon',id:del.dataset.id,_csrf:csrf}); const data=await AfenixAdmin.request('gestionar_buzones.php',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body}); await Swal.fire('Eliminado',data.message,'success'); location.reload();}catch(e){Swal.fire('Error',e.message,'error');} }
    });
    // Cierra este modal con Escape sin preguntar por cambios sin guardar.
    document.addEventListener('keydown', (event) => {
        if ((event.key === 'Escape' || event.keyCode === 27)
            && document.getElementById('mailboxModal').classList.contains('is-open')) {
            event.preventDefault();
            event.stopPropagation();
            event.stopImmediatePropagation();
            window.__afenixEscapeClosing = true;
            modal.close(true);
            window.setTimeout(() => { window.__afenixEscapeClosing = false; }, 0);
        }
    }, true);

    form.addEventListener('submit', async (event) => { event.preventDefault(); const submit=form.querySelector('[type=submit]'); submit.disabled=true; try{Swal.fire({title:'Verificando conexión...',allowOutsideClick:false,didOpen:()=>Swal.showLoading()}); const data=await AfenixAdmin.request('gestionar_buzones.php',{method:'POST',body:new FormData(form)}); modal.clean(); await Swal.fire('Guardado',data.message,'success'); location.reload();}catch(e){Swal.fire('Error',e.message,'error');}finally{submit.disabled=false;} });
});
</script>
<?php require_once __DIR__ . '/admin_footer.php'; ?>
