<?php
/**
 * API Streaming Storage Mailbox - VERSIÓN FINAL CON SOPORTE PARA LOGIN DE CUENTA ÚNICA
 */

declare(strict_types=1);

session_start(); // Iniciar sesión para acceder a las variables de consulta del usuario

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

header('Content-Type: application/json; charset=utf-8');
header('X-Content-Type-Options: nosniff');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');

function jok(array $data=[], string $title='OK', string $msg=''): void {
    $response = ['success'=>true, 'title'=>$title, 'message'=>$msg];
    if (isset($data['plataformas'])) $response['plataformas'] = $data['plataformas'];
    if (isset($data['results'])) $response['results'] = $data['results'];
    if (isset($data['html'])) $response['html'] = $data['html'];
    
    array_walk_recursive($response, function (&$item, $key) {
        if (is_string($item)) {
            $item = mb_convert_encoding($item, 'UTF-8', 'UTF-8');
        }
    });

    $json = json_encode($response);
    
    if (json_last_error() !== JSON_ERROR_NONE) {
        error_log("Error de JSON en API: " . json_last_error_msg());
        $error_response = json_encode([
            'success' => false,
            'title'   => 'Error de Procesamiento',
            'message' => 'No se pudo procesar el contenido del mensaje.'
        ]);
        echo $error_response;
        exit;
    }
    
    echo $json; 
    exit;
}

function jerr(string $title, string $msg, array $extra=[]): void {
    $response = ['success'=>false,'title'=>$title,'message'=>$msg];
    if(!empty($extra)) $response = array_merge($response, $extra);
    echo json_encode($response); exit;
}
function msys(PDO $pdo, string $clave, string $fallback): string {
    try {
        $q=$pdo->prepare("SELECT contenido FROM mensajes_sistema WHERE clave=?");
        $q->execute([$clave]);
        $r=$q->fetch(PDO::FETCH_ASSOC);
        return $r['contenido'] ?? $fallback;
    } catch(Throwable $e){ return $fallback; }
}

function msys_vars(string $message, array $variables): string {
    $replace = [];
    foreach ($variables as $key => $value) {
        $replace['{' . trim((string) $key, '{}') . '}'] = (string) $value;
    }
    return strtr($message, $replace);
}

final class PublicQueryLimitReached extends RuntimeException {}

function afenixx_register_public_query(PDO $pdo, int $adminId): void
{
    if ($adminId <= 0) return;

    $planStmt = $pdo->prepare(
        "SELECT p.limite_consultas
         FROM suscripciones s
         JOIN planes p ON p.id = s.id_plan
         WHERE s.id_admin = ? AND s.estado IN ('activa', 'prueba')
         ORDER BY s.fecha_fin DESC, s.id DESC
         LIMIT 1"
    );
    $planStmt->execute([$adminId]);
    $rawLimit = $planStmt->fetchColumn();
    if ($rawLimit === false || $rawLimit === null || (int) $rawLimit <= 0) return;

    $limit = (int) $rawLimit;
    $period = date('Y-m');

    $pdo->beginTransaction();
    try {
        $usage = $pdo->prepare(
            'SELECT consultas_realizadas FROM uso_consultas WHERE id_admin = ? AND periodo = ? FOR UPDATE'
        );
        $usage->execute([$adminId, $period]);
        $used = (int) ($usage->fetchColumn() ?: 0);
        if ($used >= $limit) {
            throw new PublicQueryLimitReached(
                "Este plan alcanzó el límite de {$limit} consultas públicas para el mes actual."
            );
        }

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

$action = $_GET['action'] ?? $_POST['action'] ?? '';

if ($action === '') { jerr('Error', msys($pdo,'API_RUTA_INVALIDA','La solicitud no es válida.')); }

if ($action === 'plataformas' || $action === 'getPlataformas') {
    try {
        $sql = "
            SELECT p.id, p.nombre, p.imagen_url, p.orden
            FROM plataformas p
            ORDER BY p.orden, p.nombre
        ";
        
        $rows = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
        if (!$rows) {
            jerr(msys($pdo, 'API_TITULO_SERVICIO_NO_DISPONIBLE', 'Servicio no disponible'), msys($pdo, 'API_PLATAFORMAS_NO_CONFIG', 'No se encontraron plataformas configuradas.'));
        }
        jok(['plataformas'=>$rows]);
    } catch(Throwable $e){
        error_log('[api.php] plataformas: '.$e->getMessage());
        jerr(msys($pdo, 'API_TITULO_SISTEMA','Ocurrió un problema'), msys($pdo, 'API_ERROR_GENERICO','Ocurrió un error inesperado.'));
    }
}

if ($action === 'realizarConsulta' || $action === 'realizarConsultaPublica') {
    $id_plataforma = isset($_POST['plataforma']) ? (int)$_POST['plataforma'] : 0;
    $correo = isset($_POST['correo']) ? trim(strtolower((string)$_POST['correo'])) : '';

    if ($id_plataforma <= 0 || !filter_var($correo, FILTER_VALIDATE_EMAIL)) {
        jerr(msys($pdo, 'API_TITULO_ATENCION', 'Atención'), msys($pdo, 'API_DATOS_INVALIDOS', 'Datos inválidos.'));
    }
    
    try {
        $q_check = $pdo->prepare("SELECT id, id_admin_propietario, id_dominio FROM correos_servicios WHERE correo = ? AND id_plataforma = ? LIMIT 1");
        $q_check->execute([$correo, $id_plataforma]);
        $cuentaRegistrada = $q_check->fetch(PDO::FETCH_ASSOC);
        if (!$cuentaRegistrada) {
            jerr(msys($pdo, 'API_TITULO_ATENCION', 'Atención'), msys($pdo, 'API_CUENTA_NO_REGISTRADA', 'Esta cuenta no está registrada.'), ['icon' => 'warning']);
        }
        $idAdminPropietario = (int) ($cuentaRegistrada['id_admin_propietario'] ?? 0);

        // Vigencia de la cuenta vendida/asignada. La fecha es inclusiva:
        // si vence hoy, todavía puede buscarse y abrirse hasta finalizar el día.
        $accountAccessService = new AccountAccessService($pdo);
        $accountAccess = $accountAccessService->statusForAccount((int) $cuentaRegistrada['id']);
        if (($accountAccess['assigned'] ?? false) && !($accountAccess['accessible'] ?? false)) {
            $expiredTitle = msys($pdo, 'API_TITULO_CUENTA_VENCIDA', 'Acceso vencido');
            $expiredMessage = msys(
                $pdo,
                'API_CUENTA_VENDIDA_VENCIDA',
                'El acceso a esta cuenta venció el {fecha_vencimiento}. Solicita la renovación a tu proveedor para volver a consultar sus mensajes.'
            );
            jerr(
                $expiredTitle,
                msys_vars($expiredMessage, [
                    'correo' => $correo,
                    'fecha_vencimiento' => (string) ($accountAccess['renewal_display'] ?? ''),
                    'cliente' => (string) ($accountAccess['client_name'] ?? 'Cliente'),
                ]),
                [
                    'icon' => 'warning',
                    'code' => 'SOLD_ACCOUNT_EXPIRED',
                    'renewal_date' => $accountAccess['renewal_date'] ?? null,
                ]
            );
        }

        $idDominioRegistrado = (int) ($cuentaRegistrada['id_dominio'] ?? 0);
        if ($idDominioRegistrado > 0) {
            $q_dom = $pdo->prepare(
                "SELECT id, nombre_dominio, id_buzon_entrada, id_admin_propietario
                 FROM dominios
                 WHERE id = ?
                 LIMIT 1"
            );
            $q_dom->execute([$idDominioRegistrado]);
        } else {
            $domainPart = strtolower((string) substr($correo, strrpos($correo, '@') + 1));
            $q_dom = $pdo->prepare(
                "SELECT id, nombre_dominio, id_buzon_entrada, id_admin_propietario
                 FROM dominios
                 WHERE nombre_dominio IN (?, ?)
                   AND (? <= 0 OR id_admin_propietario = ?)
                 ORDER BY id DESC
                 LIMIT 1"
            );
            $q_dom->execute([$domainPart, '@' . $domainPart, $idAdminPropietario, $idAdminPropietario]);
        }

        $dom = $q_dom->fetch(PDO::FETCH_ASSOC);
        if (!$dom || empty($dom['id_buzon_entrada'])) {
            jerr(
                msys($pdo, 'API_TITULO_ATENCION', 'Atención'),
                msys($pdo, 'API_BUZON_NO_CONFIGURADO', 'El servicio no está configurado para este dominio.'),
                ['code' => 'MAILBOX_NOT_CONFIGURED']
            );
        }
        if ($idAdminPropietario <= 0) {
            $idAdminPropietario = (int) ($dom['id_admin_propietario'] ?? 0);
        }

        $q_imap = $pdo->prepare("SELECT * FROM configuraciones_imap WHERE id=? LIMIT 1");
        $q_imap->execute([$dom['id_buzon_entrada']]);
        $imapConf=$q_imap->fetch(PDO::FETCH_ASSOC);
        if (!$imapConf) {
            jerr(msys($pdo, 'API_TITULO_ATENCION', 'Atención'), msys($pdo, 'API_BUZON_NO_CONFIGURADO', 'No se encontró la configuración del buzón.'));
        }

        // Seleccionamos da.es_publico (el específico del dominio)
        $q_asuntos = $pdo->prepare("
            SELECT a.id, a.nombre, a.es_flexible, da.es_publico AS visible_publico 
            FROM asuntos a 
            INNER JOIN dominio_asunto da ON da.id_asunto = a.id 
            WHERE a.id_plataforma = ? AND da.id_dominio = ? 
            ORDER BY a.nombre
        ");
        $q_asuntos->execute([$id_plataforma, $dom['id']]);
        $asuntos=$q_asuntos->fetchAll(PDO::FETCH_ASSOC);
        
        if (!$asuntos) {
            jerr(msys($pdo, 'API_TITULO_SIN_RESULTADOS', 'Sin resultados'), msys($pdo, 'API_SIN_ASUNTOS_CONFIGURADOS', 'No hay asuntos configurados.'));
        }

        require_once __DIR__ . '/IMAPHandler.php';
        $imap = new IMAPHandler($pdo);
        
        if ($action === 'realizarConsultaPublica') {
            afenixx_register_public_query($pdo, $idAdminPropietario);
            $resultados = $imap->buscarTodosLosAsuntos($imapConf, $correo, $asuntos);
            if (!empty($resultados)) {
                jok(['results' => $resultados]);
            }

            if ($imap->getLastError() !== '') {
                jerr(
                    msys($pdo, 'API_TITULO_SISTEMA', 'Buzón no disponible'),
                    $imap->getLastError(),
                    ['icon' => 'warning', 'code' => 'IMAP_CONNECTION']
                );
            }

            jerr(
                msys($pdo, 'API_TITULO_SIN_RESULTADOS', 'Sin resultados'),
                msys($pdo, 'API_SIN_RESULTADOS', 'No se encontraron correos recientes.'),
                ['icon' => 'warning']
            );
        }
        
        if ($action === 'realizarConsulta') {
            $id_asunto = isset($_POST['asunto']) ? (int)$_POST['asunto'] : 0;
            
            // =========================================================================
            //          INICIO DE LA VALIDACIÓN DE PROPIEDAD Y PERMISOS
            // =========================================================================
            $id_usuario_logueado = $_SESSION['consulta']['uid'] ?? null;
            $tipo_acceso = $_SESSION['consulta']['tipo_acceso'] ?? null; // 'cliente' o 'cuenta_unica'
            
            // Verificar visibilidad por dominio
            $id_dominio_actual = $dom['id'];
            $es_publico = 0;
            if ($id_dominio_actual) {
                $stmt_asunto = $pdo->prepare("SELECT es_publico FROM dominio_asunto WHERE id_dominio = ? AND id_asunto = ?");
                $stmt_asunto->execute([$id_dominio_actual, $id_asunto]);
                $es_publico = $stmt_asunto->fetchColumn();
            }

            // SI EL MENSAJE ES PRIVADO...
            if ($es_publico == 0) { 
                // Verificar si hay algún tipo de sesión iniciada
                if (!isset($_SESSION['consulta']['codigo_consulta'])) {
                    jerr(msys($pdo, 'API_TITULO_ACCESO_REQUERIDO', 'Acceso Requerido'), msys($pdo, 'API_ACCESO_REQUERIDO_LOGIN', 'Necesita iniciar sesión para ver este mensaje.'), ['icon' => 'info']);
                }

                $tiene_permiso = false;

                // CASO 1: ACCESO POR CUENTA ÚNICA
                if ($tipo_acceso === 'cuenta_unica') {
                    $correo_permitido = $_SESSION['consulta']['correo_permitido'] ?? '';
                    // Si el correo que intenta consultar coincide EXACTAMENTE con el autorizado
                    if (strtolower($correo) === strtolower($correo_permitido)) {
                        $tiene_permiso = true;
                    } else {
                        jerr(msys($pdo, 'API_TITULO_ACCESO_DENEGADO', 'Acceso Denegado'), 'Este código solo permite consultar la cuenta: ' . $correo_permitido, ['icon' => 'error']);
                    }
                } 
                // CASO 2: ACCESO POR CLIENTE (REVENDEDOR/FINAL)
                else {
                    $stmt_permiso = $pdo->prepare("
                        SELECT COUNT(a.id) 
                        FROM asociaciones a 
                        INNER JOIN correos_servicios cs ON a.id_correo_servicio = cs.id 
                        WHERE a.id_usuario = ? AND cs.correo = ? AND cs.id_plataforma = ?
                    ");
                    $stmt_permiso->execute([$id_usuario_logueado, $correo, $id_plataforma]);
                    if ($stmt_permiso->fetchColumn() > 0) {
                        $tiene_permiso = true;
                    }
                }

                if (!$tiene_permiso) {
                    jerr(msys($pdo, 'API_TITULO_ACCESO_DENEGADO', 'Acceso Denegado'), msys($pdo, 'API_ACCESO_DENEGADO', 'No tienes permiso para consultar la información de este correo.'), ['icon' => 'error']);
                }
            }
            // =========================================================================
            //          FIN DE LA VALIDACIÓN
            // =========================================================================

            // La búsqueda puede listar resultados aunque el Admin propietario esté vencido,
            // pero el contenido no se abre hasta que su suscripción vuelva a estar operativa.
            $subscriptionAccess = new SubscriptionAccessService($pdo);
            if ($idAdminPropietario > 0 && !$subscriptionAccess->canOpenSearchResult($idAdminPropietario)) {
                $ownerStatus = $subscriptionAccess->statusForAdmin($idAdminPropietario);
                jerr(
                    'Acceso temporalmente suspendido',
                    'La cuenta fue localizada, pero el contenido no puede abrirse porque la suscripción del administrador está vencida. Inténtalo nuevamente cuando el servicio sea renovado.',
                    [
                        'icon' => 'warning',
                        'code' => 'OWNER_SUBSCRIPTION_EXPIRED',
                        'subscription_state' => $ownerStatus['state'] ?? 'vencida',
                    ]
                );
            }

            $result = $imap->buscarUnAsunto($imapConf, $correo, $asuntos, $id_asunto);

            if (!$result['ok']) {
                jerr($result['title'], $result['message'], ['icon' => 'warning']);
            }

            $stmt_plat = $pdo->prepare("SELECT nombre, imagen_url FROM plataformas WHERE id = ?");
            $stmt_plat->execute([$id_plataforma]);
            $platform_info = $stmt_plat->fetch(PDO::FETCH_ASSOC);

            // AFENIXX-MODAL-LOGO-V10
            $platform_name = trim(
                (string) ($platform_info['nombre'] ?? '')
            );

            if ($platform_name === '') {
                $platform_name = 'Plataforma';
            }

            $platform_logo = trim(
                (string) ($platform_info['imagen_url'] ?? '')
            );

            if ($platform_logo !== '') {
                $platform_logo_html =
                    '<span class="inline-flex items-center justify-center '
                    . 'w-11 h-11 min-w-11 rounded-xl border border-gray-200 '
                    . 'bg-white shadow-sm overflow-hidden p-2">'
                    . '<img src="'
                    . htmlspecialchars(
                        $platform_logo,
                        ENT_QUOTES | ENT_SUBSTITUTE,
                        'UTF-8'
                    )
                    . '" alt="'
                    . htmlspecialchars(
                        $platform_name,
                        ENT_QUOTES | ENT_SUBSTITUTE,
                        'UTF-8'
                    )
                    . '" class="w-full h-full object-contain" '
                    . 'loading="lazy" '
                    . 'onerror="this.style.display=\'none\';'
                    . 'this.nextElementSibling.style.display=\'inline-flex\';">'
                    . '<span style="display:none" '
                    . 'class="w-full h-full items-center justify-center '
                    . 'text-red-600">'
                    . '<i class="fas fa-tv text-base"></i>'
                    . '</span>'
                    . '</span>';
            } else {
                $platform_logo_html =
                    '<span class="inline-flex items-center justify-center '
                    . 'w-11 h-11 min-w-11 rounded-xl border border-gray-200 '
                    . 'bg-white shadow-sm text-red-600">'
                    . '<i class="fas fa-tv text-base"></i>'
                    . '</span>';
            }

            $html_content = '<div class="bg-white rounded-lg shadow-xl w-full max-w-4xl mx-4"><div class="bg-red-600 text-white p-4 flex justify-between items-center rounded-t-lg" style="background-color:#dc2626"><h3 class="text-xl font-bold">Detalle de la Consulta</h3><button id="closeModalButton" class="text-2xl font-bold leading-none hover:text-gray-300">&times;</button></div><div class="p-6 grid grid-cols-1 md:grid-cols-4 gap-6"><div class="md:col-span-1 md:border-r md:border-gray-200 md:pr-6"><h4 class="font-bold text-gray-800 mb-2">Plataforma:</h4><div class="flex items-center gap-3 mb-5">'.$platform_logo_html.'<div class="min-w-0"><span class="block text-xs font-semibold uppercase tracking-wide text-gray-400">Servicio</span><span class="block font-bold text-sm text-gray-900 truncate">'.htmlspecialchars($platform_name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').'</span></div></div><h4 class="font-bold text-gray-800 mb-2">Asunto:</h4><p class="text-xs text-gray-600 mb-4">'.htmlspecialchars($result['data']['subject']).'</p><h4 class="font-bold text-gray-800 mb-2">Correo Consultado:</h4><p class="text-xs text-gray-600 break-all">'.htmlspecialchars($correo).'</p></div><div class="md:col-span-3"><h4 class="font-bold text-gray-800 mb-4">Mensaje Encontrado</h4><div class="border rounded-lg p-4 bg-gray-50" style="max-height:400px;overflow-y:auto"><div class="prose max-w-none">'.$result['data']['html'].'</div></div></div></div><div class="bg-gray-100 p-4 flex justify-end rounded-b-lg border-t"><button id="closeModalButtonFooter" class="bg-gray-500 text-white py-2 px-4 rounded-lg hover:bg-gray-600 transition-colors">Cerrar</button></div></div>';
            
            jok(['html' => $html_content]);
        }

    } catch (PublicQueryLimitReached $e) {
        jerr('Límite de consultas alcanzado', $e->getMessage(), ['icon' => 'warning']);
    } catch(Throwable $e){
        error_log('[api.php] Exception: '.$e->getMessage());
        jerr(msys($pdo,'API_TITULO_SISTEMA','Ocurrió un problema'), msys($pdo,'API_ERROR_GENERICO','Ocurrió un error inesperado.'));
    }
}

jerr('Error', msys($pdo,'API_RUTA_INVALIDA','La solicitud no es válida.'), ['icon' => 'error']);