<?php
namespace Thirty\controllers;

class NotificationController 
{
    private static function getUserID()
    {
        require_auth();
        return user()['id'];
    }

    private static function closeSession()
    {
        if (session_status() === PHP_SESSION_ACTIVE) {
            session_write_close();
        }
    }

    private static function getUnreadCount($userID)
    {
        global $DB;
        $st = $DB->prepare('SELECT COUNT(*) FROM notifications WHERE user_id = ? AND read_at IS NULL');
        $st->execute([$userID]);
        return (int)$st->fetchColumn();
    }

    private static function prepareNotificationData($row)
    {
        return [
            'id' => (int)$row['id'],
            'type' => $row['type'],
            'payload' => json_decode($row['payload'] ?? '{}', true) ?: [],
            'read_at' => $row['read_at'],
            'created_at' => $row['created_at']
        ];
    }

    public static function index()
    {
        $userID = self::getUserID();
        global $DB;
        
        $st = $DB->prepare('
            SELECT id, type, payload, read_at, created_at 
            FROM notifications 
            WHERE user_id = ? 
            ORDER BY created_at DESC 
            LIMIT 100
        ');
        $st->execute([$userID]);
        $notifications = $st->fetchAll();
        
        view('notifications/index', ['items' => $notifications]);
    }

    public static function stream()
    {
        $userID = self::getUserID();
        self::closeSession();
        
        // Configuración SSE con UTF-8
        header('Content-Type: text/event-stream; charset=utf-8');
        header('Cache-Control: no-cache, no-store, must-revalidate');
        header('Pragma: no-cache');
        header('Expires: 0');
        header('X-Accel-Buffering: no');
        
        @ini_set('output_buffering', 'off');
        @ini_set('zlib.output_compression', 0);
        @ini_set('implicit_flush', 1);
        
        ignore_user_abort(true);
        @set_time_limit(0);

        // Headers iniciales SSE
        echo ":" . str_repeat(' ', 2048) . "\n";
        echo "retry: 3000\n";
        @ob_flush();
        @flush();

        // Obtener último ID
        $lastID = 0;
        if (isset($_SERVER['HTTP_LAST_EVENT_ID'])) {
            $lastID = max($lastID, (int)$_SERVER['HTTP_LAST_EVENT_ID']);
        }
        if (isset($_GET['last_id'])) {
            $lastID = max($lastID, (int)$_GET['last_id']);
        }

        // Enviar estado inicial
        $unreadCount = self::getUnreadCount($userID);
        self::sendSSEEvent('init', ['unread' => $unreadCount], $lastID);

        // Bucle principal de notificaciones
        $maxExecutionTime = 30; // segundos
        $pollInterval = 2; // segundos
        $startTime = time();
        
        try {
            while ((time() - $startTime) < $maxExecutionTime) {
                if (connection_aborted()) {
                    break;
                }
                
                // Buscar TODAS las notificaciones nuevas
                $newNotifications = self::getNewNotifications($userID, $lastID);
                
                foreach ($newNotifications as $notification) {
                    $lastID = max($lastID, $notification['id']);
                    
                    // Solo enviar evento si la notificación no está leída
                    if (!$notification['read_at']) {
                        self::sendSSEEvent('notify', $notification, $lastID);
                    }
                }
                
                // Keep-alive cada 15 segundos
                if ((time() - $startTime) % 15 === 0) {
                    echo ": keep-alive\n\n";
                    @ob_flush();
                    @flush();
                }
                
                sleep($pollInterval);
            }
        } catch (\Exception $e) {
            error_log("SSE Error: " . $e->getMessage());
        }
        
        echo "event: end\n";
        echo "data: {\"message\": \"session_ended\"}\n\n";
        @ob_flush();
        @flush();
    }

    private static function sendSSEEvent($event, $data, $id = null)
    {
        if ($id !== null) {
            echo "id: " . $id . "\n";
        }
        echo "event: " . $event . "\n";
        echo "data: " . json_encode($data, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) . "\n\n";
        echo str_repeat(" ", 1024) . "\n";
        @ob_flush();
        @flush();
    }

    private static function getNewNotifications($userID, $lastID)
    {
        global $DB;
        // Buscar TODAS las notificaciones nuevas
        $st = $DB->prepare('
            SELECT id, type, payload, read_at, created_at 
            FROM notifications 
            WHERE user_id = ? AND id > ? 
            ORDER BY id ASC 
            LIMIT 50
        ');
        $st->execute([$userID, $lastID]);
        $rows = $st->fetchAll();
        
        $notifications = [];
        foreach ($rows as $row) {
            $notifications[] = self::prepareNotificationData($row);
        }
        
        return $notifications;
    }

    public static function unread_count()
    {
        $userID = self::getUserID();
        self::closeSession();
        
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-cache, no-store, must-revalidate');
        
        try {
            $count = self::getUnreadCount($userID);
            echo json_encode([
                'ok' => true, 
                'count' => $count,
                'timestamp' => time()
            ], JSON_UNESCAPED_UNICODE);
        } catch (\Exception $e) {
            http_response_code(500);
            echo json_encode([
                'ok' => false, 
                'error' => 'Error retrieving notification count',
                'timestamp' => time()
            ], JSON_UNESCAPED_UNICODE);
        }
        exit;
    }

    public static function latest()
    {
        $userID = self::getUserID();
        self::closeSession();
        
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-cache, no-store, must-revalidate');
        
        global $DB;
        try {
            // Mostrar las últimas notificaciones (leídas y no leídas)
            $st = $DB->prepare('
                SELECT id, type, payload, created_at, read_at 
                FROM notifications 
                WHERE user_id = ? 
                ORDER BY created_at DESC 
                LIMIT 15
            ');
            $st->execute([$userID]);
            $notifications = $st->fetchAll();
            
            $formattedNotifications = [];
            foreach ($notifications as $notification) {
                $formattedNotifications[] = self::prepareNotificationData($notification);
            }
            
            echo json_encode([
                'ok' => true,
                'items' => $formattedNotifications,
                'total' => count($formattedNotifications),
                'unread_count' => self::getUnreadCount($userID),
                'timestamp' => time()
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        } catch (\Exception $e) {
            http_response_code(500);
            echo json_encode([
                'ok' => false,
                'error' => 'Error retrieving notifications',
                'timestamp' => time()
            ], JSON_UNESCAPED_UNICODE);
        }
        exit;
    }

    public static function mark_read()
    {
        $userID = self::getUserID();
        verify_csrf();
        global $DB;
        
        $notificationID = isset($_POST['id']) ? (int)$_POST['id'] : 0;
        
        try {
            if ($notificationID > 0) {
                $st = $DB->prepare('
                    UPDATE notifications 
                    SET read_at = NOW() 
                    WHERE id = ? AND user_id = ? AND read_at IS NULL
                ');
                $st->execute([$notificationID, $userID]);
                $affectedRows = $st->rowCount();
            } else {
                $st = $DB->prepare('
                    UPDATE notifications 
                    SET read_at = NOW() 
                    WHERE user_id = ? AND read_at IS NULL
                ');
                $st->execute([$userID]);
                $affectedRows = $st->rowCount();
            }
            
            // Redireccionar con mensaje de éxito
            if ($notificationID > 0) {
                $_SESSION['flash'] = $affectedRows > 0 
                    ? 'Notificación marcada como leída' 
                    : 'La notificación ya estaba marcada como leída';
            } else {
                $_SESSION['flash'] = $affectedRows > 0 
                    ? $affectedRows . ' notificaciones marcadas como leídas' 
                    : 'No había notificaciones pendientes';
            }
                
        } catch (\Exception $e) {
            $_SESSION['flash'] = 'Error al marcar la notificación como leída';
        }
        
        header('Location: ' . base_url('/notifications'));
        exit;
    }

    public static function mark_all_read_json()
    {
        $userID = self::getUserID();
        self::closeSession();
        
        header('Content-Type: application/json; charset=utf-8');
        
        global $DB;
        try {
            $st = $DB->prepare('
                UPDATE notifications 
                SET read_at = NOW() 
                WHERE user_id = ? AND read_at IS NULL
            ');
            $st->execute([$userID]);
            $affectedRows = $st->rowCount();
            
            echo json_encode([
                'ok' => true,
                'message' => 'Todas las notificaciones marcadas como leídas',
                'affected_count' => $affectedRows,
                'unread_count' => 0,
                'timestamp' => time()
            ], JSON_UNESCAPED_UNICODE);
        } catch (\Exception $e) {
            http_response_code(500);
            echo json_encode([
                'ok' => false,
                'error' => 'Error al marcar las notificaciones como leídas',
                'timestamp' => time()
            ], JSON_UNESCAPED_UNICODE);
        }
        exit;
    }

    public static function delete()
    {
        $userID = self::getUserID();
        verify_csrf();
        global $DB;
        
        $notificationID = isset($_POST['id']) ? (int)$_POST['id'] : 0;
        
        if ($notificationID <= 0) {
            $_SESSION['flash'] = 'ID de notificación no válido';
            header('Location: ' . base_url('/notifications'));
            exit;
        }
        
        try {
            // Verificar que la notificación pertenece al usuario
            $st = $DB->prepare('SELECT id FROM notifications WHERE id = ? AND user_id = ?');
            $st->execute([$notificationID, $userID]);
            $notification = $st->fetch();
            
            if (!$notification) {
                $_SESSION['flash'] = 'Notificación no encontrada';
                header('Location: ' . base_url('/notifications'));
                exit;
            }
            
            // Eliminar la notificación
            $st = $DB->prepare('DELETE FROM notifications WHERE id = ? AND user_id = ?');
            $st->execute([$notificationID, $userID]);
            $affectedRows = $st->rowCount();
            
            if ($affectedRows > 0) {
                $_SESSION['flash'] = 'Notificación eliminada correctamente';
            } else {
                $_SESSION['flash'] = 'No se pudo eliminar la notificación';
            }
                
        } catch (\Exception $e) {
            $_SESSION['flash'] = 'Error al eliminar la notificación: ' . $e->getMessage();
        }
        
        header('Location: ' . base_url('/notifications'));
        exit;
    }

    public static function delete_all_read()
    {
        $userID = self::getUserID();
        verify_csrf();
        global $DB;
        
        try {
            $st = $DB->prepare('
                DELETE FROM notifications 
                WHERE user_id = ? AND read_at IS NOT NULL
            ');
            $st->execute([$userID]);
            $affectedRows = $st->rowCount();
            
            $_SESSION['flash'] = $affectedRows > 0 
                ? $affectedRows . ' notificaciones leídas eliminadas' 
                : 'No había notificaciones leídas para eliminar';
        } catch (\Exception $e) {
            $_SESSION['flash'] = 'Error al eliminar las notificaciones';
        }
        
        header('Location: ' . base_url('/notifications'));
        exit;
    }

    public static function redirect_to_content()
    {
        $userID = self::getUserID();
        $notificationID = isset($_GET['id']) ? (int)$_GET['id'] : 0;
        
        if ($notificationID <= 0) {
            $_SESSION['flash'] = 'Notificación no válida';
            header('Location: ' . base_url('/notifications'));
            exit;
        }
        
        global $DB;
        
        try {
            // Obtener la notificación
            $st = $DB->prepare('
                SELECT type, payload, read_at 
                FROM notifications 
                WHERE id = ? AND user_id = ?
            ');
            $st->execute([$notificationID, $userID]);
            $notification = $st->fetch();
            
            if (!$notification) {
                $_SESSION['flash'] = 'Notificación no encontrada';
                header('Location: ' . base_url('/notifications'));
                exit;
            }
            
            // Marcar como leída si no lo está
            if (!$notification['read_at']) {
                $st = $DB->prepare('
                    UPDATE notifications 
                    SET read_at = NOW() 
                    WHERE id = ? AND user_id = ?
                ');
                $st->execute([$notificationID, $userID]);
            }
            
            $payload = json_decode($notification['payload'] ?? '{}', true) ?: [];
            $type = $notification['type'];
            
            // Redirigir según el tipo de notificación - SOLUCIÓN DEFINITIVA
            switch ($type) {
                case 'like':
                case 'comment':
                    $postID = $payload['post_id'] ?? null;
                    if ($postID) {
                        header('Location: ' . base_url('/photo?id=' . $postID));
                        exit;
                    }
                    break;
                    
                case 'friend_request':
                case 'friend_accept':
                    // SOLUCIÓN: Redirigir siempre a la vista de amigos
                    header('Location: ' . base_url('/friends'));
                    exit;
            }
            
            // Si no se pudo redirigir a contenido específico, ir a notificaciones
            $_SESSION['flash'] = 'No se pudo encontrar el contenido de la notificación';
            header('Location: ' . base_url('/notifications'));
            exit;
            
        } catch (\Exception $e) {
            $_SESSION['flash'] = 'Error al procesar la notificación';
            header('Location: ' . base_url('/notifications'));
            exit;
        }
    }
}