<?php
// src/controllers/PostController.php
class PostController {

    public static function index($db) {
        require_login();
        $uid = $_SESSION['user']['id'];
        
        $posts = $db->prepare("
            SELECT p.*, ph.url, 
                   (SELECT COUNT(*) FROM likes WHERE post_id = p.id) as likes,
                   (SELECT COUNT(*) FROM comments WHERE post_id = p.id) as comments,
                   (SELECT COUNT(*) FROM tags WHERE post_id = p.id) as tags_count
            FROM posts p
            LEFT JOIN photos ph ON ph.post_id = p.id
            WHERE p.author_id = ?
            ORDER BY p.created_at DESC
        ");
        $posts->execute([$uid]);
        
        view('posts/list', [
            'posts' => $posts->fetchAll()
        ]);
    }
    
    public static function list($db) {
        self::index($db);
    }
    
    public static function create($db) {
        require_login();
        $uid = $_SESSION['user']['id'];
        
        // Verificar que el usuario tiene permisos para publicar
        $user_check = $db->prepare("SELECT email_verified, locked_until FROM users WHERE id = ?");
        $user_check->execute([$uid]);
        $user = $user_check->fetch();
        
        if (!$user || !$user['email_verified']) {
            flash('error', 'Debes verificar tu email antes de publicar.');
            redirect('dashboard');
            return;
        }
        
        if ($user['locked_until'] && strtotime($user['locked_until']) > time()) {
            flash('error', 'Tu cuenta está temporalmente bloqueada.');
            redirect('dashboard');
            return;
        }

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            validate_csrf();
            
            $caption = trim($_POST['caption'] ?? '');
            
            // Validar longitud del caption
            if (strlen($caption) > 500) {
                flash('error', 'El pie de foto no puede exceder los 500 caracteres.');
                redirect('posts/new');
                return;
            }
            
            // Validar contenido malicioso en el caption
            if (self::containsMaliciousContent($caption)) {
                SecurityHelper::logSecurityEvent($db, 'malicious_content', 'Intento de publicación con contenido malicioso: ' . substr($caption, 0, 100), $uid);
                flash('error', 'El contenido contiene texto no permitido.');
                redirect('posts/new');
                return;
            }

            if (!isset($_FILES['photo']) || $_FILES['photo']['error'] !== UPLOAD_ERR_OK) {
                flash('error', 'Debes seleccionar una imagen');
                redirect('posts/new');
                return;
            }
            
            $file = $_FILES['photo'];
            $allowed = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/webp' => 'webp'];
            $max_size = 5 * 1024 * 1024; // 5MB
            
            if ($file['size'] > $max_size) {
                flash('error', 'La imagen es demasiado grande. Máximo 5MB');
                redirect('posts/new');
                return;
            }
            
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            $mime = finfo_file($finfo, $file['tmp_name']);
            finfo_close($finfo);

            if (!isset($allowed[$mime])) {
                flash('error', 'Formato no permitido. Solo JPG, PNG o WEBP');
                redirect('posts/new');
                return;
            }

            // Verificar que es una imagen real
            if (!getimagesize($file['tmp_name'])) {
                flash('error', 'El archivo no es una imagen válida.');
                redirect('posts/new');
                return;
            }

            global $CONFIG;
            $filename = 'post_' . $uid . '_' . time() . '_' . bin2hex(random_bytes(8)) . '.' . $allowed[$mime];
            $upload_dir = $CONFIG['upload_dir'] . '/posts/';
            $dest = $upload_dir . $filename;
            
            if (!is_dir($upload_dir)) {
                mkdir($upload_dir, 0755, true);
            }
            
            if (move_uploaded_file($file['tmp_name'], $dest)) {
                $db->beginTransaction();
                
                try {
                    $post_id = self::generateUUID();
                    $post_stmt = $db->prepare("INSERT INTO posts (id, author_id, caption, created_at) VALUES (?, ?, ?, ?)");
                    $post_stmt->execute([$post_id, $uid, $caption, gmdate('Y-m-d H:i:s')]);
                    
                    $photo_stmt = $db->prepare("INSERT INTO photos (id, post_id, url, created_at) VALUES (?, ?, ?, ?)");
                    $photo_url = $CONFIG['upload_url'] . '/posts/' . $filename;
                    $photo_id = self::generateUUID();
                    $photo_stmt->execute([$photo_id, $post_id, $photo_url, gmdate('Y-m-d H:i:s')]);
                    
                    $db->commit();
                    
                    // Registrar evento de seguridad
                    SecurityHelper::logSecurityEvent($db, 'post_created', 'Nueva publicación creada', $uid);
                    
                    flash('success', 'Publicación creada correctamente');
                    redirect('posts');
                    
                } catch (Exception $e) {
                    $db->rollBack();
                    if (file_exists($dest)) {
                        unlink($dest);
                    }
                    error_log("Error creating post: " . $e->getMessage());
                    SecurityHelper::logSecurityEvent($db, 'post_creation_error', 'Error al crear publicación: ' . $e->getMessage(), $uid);
                    flash('error', 'Error al crear la publicación');
                    redirect('posts/new');
                }
            } else {
                flash('error', 'Error al subir la imagen');
                redirect('posts/new');
            }
        }
        
        view('posts/create', []);
    }

    private static function generateUUID() {
        return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
        );
    }

    public static function view($db) {
        require_login();
        $uid = $_SESSION['user']['id'];
        $post_id = $_GET['id'] ?? ($_POST['post_id'] ?? '');
        
        if (empty($post_id)) {
            flash('error', 'Publicación no válida');
            redirect('posts');
            return;
        }
        
        // Verificar si el usuario es admin/moderator
        $isAdmin = isset($_SESSION['user']['role']) && in_array($_SESSION['user']['role'], ['admin', 'moderator']);
        
        // Consulta base para obtener el post
        $sql = "
            SELECT p.*, u.username, u.avatar_url,
                   (SELECT COUNT(*) FROM likes WHERE post_id = p.id AND user_id = ?) as is_liked
            FROM posts p 
            JOIN users u ON p.author_id = u.id 
            WHERE p.id = ?
        ";
        
        $params = [$uid, $post_id];
        
        // Si no es admin, aplicar restricciones de visibilidad
        if (!$isAdmin) {
            $sql .= " AND (
                p.author_id = ? 
                OR EXISTS (
                    SELECT 1 FROM friends f 
                    WHERE (
                        (f.user1_id = p.author_id AND f.user2_id = ?) 
                        OR (f.user1_id = ? AND f.user2_id = p.author_id)
                    ) 
                    AND f.status = 'accepted'
                )
                OR p.visibility = 'public'
            )";
            $params[] = $uid;
            $params[] = $uid;
            $params[] = $uid;
        }
        
        $post_stmt = $db->prepare($sql);
        $post_stmt->execute($params);
        $post = $post_stmt->fetch();
        
        if (!$post) {
            flash('error', 'Publicación no encontrada o no tienes permiso para verla');
            redirect('posts');
            return;
        }
        
        $is_author = ($post['author_id'] == $uid);
        
        $photo_stmt = $db->prepare("SELECT * FROM photos WHERE post_id = ?");
        $photo_stmt->execute([$post_id]);
        $photo = $photo_stmt->fetch();
        
        $tags_stmt = $db->prepare("SELECT t.*, t.name as name FROM tags t WHERE t.post_id = ?");
        $tags_stmt->execute([$post_id]);
        $tags = $tags_stmt->fetchAll();
        
        $comments_stmt = $db->prepare("
            SELECT c.*, u.username, u.avatar_url,
                   (c.user_id = ? OR p.author_id = ?) as can_delete
            FROM comments c 
            JOIN users u ON c.user_id = u.id 
            JOIN posts p ON c.post_id = p.id
            WHERE c.post_id = ? AND c.reply_to IS NULL 
            ORDER BY c.created_at ASC
        ");
        $comments_stmt->execute([$uid, $uid, $post_id]);
        $comments = $comments_stmt->fetchAll();

// === Enriquecer comentarios con avatar y username del autor del comentario ===
$__cids = array();
foreach ($comments as $__c) {
    if (!empty($__c['user_id'])) {
        $__cids[(string)$__c['user_id']] = true;
    }
}
$__cids = array_keys($__cids);
if ($__cids) {
    $__in = implode(',', array_fill(0, count($__cids), '?'));
    try {
        $__st = $db->prepare("SELECT id, username, avatar_url FROM users WHERE id IN ($__in)");
        $__st->execute($__cids);
        $__map = array();
        while ($__r = $__st->fetch(PDO::FETCH_ASSOC)) {
            $__map[(string)$__r['id']] = $__r;
        }
        foreach ($comments as &$__c) {
            $__uid = isset($__c['user_id']) ? (string)$__c['user_id'] : '';
            if ($__uid && isset($__map[$__uid])) {
                $__c['commenter_username']   = $__map[$__uid]['username'];
                $__c['commenter_avatar_url'] = $__map[$__uid]['avatar_url'];
            }
        }
        unset($__c);
    } catch (\Exception $__e) { /* noop */ }
}

        
        foreach ($comments as &$comment) {
            $replies_stmt = $db->prepare("
                SELECT c.*, u.username, u.avatar_url,
                       (c.user_id = ? OR p.author_id = ?) as can_delete
                FROM comments c 
                JOIN users u ON c.user_id = u.id 
                JOIN posts p ON c.post_id = p.id
                WHERE c.reply_to = ? 
                ORDER BY c.created_at ASC
            ");
            $replies_stmt->execute([$uid, $uid, $comment['id']]);
            $comment['replies'] = $replies_stmt->fetchAll();
        }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            validate_csrf();
            
            if (isset($_POST['delete_comment'])) {
                $comment_id = $_POST['comment_id'] ?? '';
                
                if (!empty($comment_id)) {
                    try {
                        $check_stmt = $db->prepare("
                            SELECT c.*, p.author_id as post_author_id 
                            FROM comments c 
                            JOIN posts p ON c.post_id = p.id 
                            WHERE c.id = ? AND (c.user_id = ? OR p.author_id = ?)
                        ");
                        $check_stmt->execute([$comment_id, $uid, $uid]);
                        $comment_to_delete = $check_stmt->fetch();
                        
                        if ($comment_to_delete) {
                            $delete_stmt = $db->prepare("DELETE FROM comments WHERE id = ? OR reply_to = ?");
                            $success = $delete_stmt->execute([$comment_id, $comment_id]);
                            
                            if ($success) {
                                SecurityHelper::logSecurityEvent($db, 'comment_deleted', 'Comentario eliminado: ' . $comment_id, $uid);
                                flash('success', 'Comentario eliminado correctamente');
                            } else {
                                flash('error', 'Error al eliminar el comentario');
                            }
                        } else {
                            SecurityHelper::logSecurityEvent($db, 'unauthorized_comment_delete', 'Intento de eliminar comentario ajeno: ' . $comment_id, $uid);
                            flash('error', 'No tienes permiso para eliminar este comentario');
                        }
                    } catch (Exception $e) {
                        error_log("Error al eliminar comentario: " . $e->getMessage());
                        SecurityHelper::logSecurityEvent($db, 'comment_deletion_error', 'Error al eliminar comentario: ' . $e->getMessage(), $uid);
                        flash('error', 'Error del sistema al eliminar el comentario');
                    }
                }
                
                header("Location: ./?r=posts/view&id=" . $post_id);
                exit;
            }
            
            if (isset($_POST['add_comment'])) {
                $comment_text = trim($_POST['comment'] ?? '');
                $reply_to = $_POST['reply_to'] ?? null;

                // Enforce max length to match DB (e.g., VARCHAR(255))
                if (mb_strlen($comment_text) > 255) {
                    $comment_text = mb_substr($comment_text, 0, 255);
                }
                // Validar contenido malicioso
                if (self::containsMaliciousContent($comment_text)) {
                    SecurityHelper::logSecurityEvent($db, 'malicious_comment', 'Intento de comentario con contenido malicioso', $uid);
                    flash('error', 'El comentario contiene texto no permitido.');
                    header("Location: ./?r=posts/view&id=" . $post_id);
                    exit;
                }
                
                if (!empty($comment_text)) {
                    try {
                        if (!empty($reply_to)) {
                            $check_reply = $db->prepare("SELECT id FROM comments WHERE id = ? AND post_id = ?");
                            $check_reply->execute([$reply_to, $post_id]);
                            
                            if ($check_reply->fetch()) {
                                $comment_stmt = $db->prepare("
                                    INSERT INTO comments (id, post_id, user_id, comment, reply_to, created_at) 
                                    VALUES (?, ?, ?, ?, ?, ?)
                                ");
                                $comment_id = self::generateUUID();
                                $success = $comment_stmt->execute([$comment_id, $post_id, $uid, $comment_text, $reply_to, gmdate('Y-m-d H:i:s')]);
                                self::notifyCommentReply($db, $reply_to, $uid, $post_id);
                                SecurityHelper::logSecurityEvent($db, 'comment_reply', 'Respuesta a comentario: ' . $reply_to, $uid);
                            } else {
                                flash('error', 'El comentario al que intentas responder no existe');
                                header("Location: ./?r=posts/view&id=" . $post_id);
                                exit;
                            }
                        } else {
                            $comment_stmt = $db->prepare("
                                INSERT INTO comments (id, post_id, user_id, comment, created_at) 
                                VALUES (?, ?, ?, ?, ?)
                            ");
                            $comment_id = self::generateUUID();
                            $success = $comment_stmt->execute([$comment_id, $post_id, $uid, $comment_text, gmdate('Y-m-d H:i:s')]);
                            if ($post['author_id'] != $uid) {
                                self::notifyNewComment($db, $post['author_id'], $uid, $post_id);
                            }
                            SecurityHelper::logSecurityEvent($db, 'new_comment', 'Nuevo comentario en publicación: ' . $post_id, $uid);
                        }
                        
                        if ($success) {
                            flash('success', 'Comentario publicado');
                        } else {
                            flash('error', 'Error al publicar el comentario');
                        }
                    } catch (Exception $e) {
                        error_log("Error al insertar comentario: " . $e->getMessage());
                        SecurityHelper::logSecurityEvent($db, 'comment_error', 'Error al publicar comentario: ' . $e->getMessage(), $uid);
                        flash('error', 'Error del sistema al publicar el comentario');
                    }
                } else {
                    flash('error', 'El comentario no puede estar vacío');
                }
                
                header("Location: ./?r=posts/view&id=" . $post_id);
                exit;
            }
            
            if (isset($_POST['add_tag'])) {
                if (!$is_author && !$isAdmin) {
                    SecurityHelper::logSecurityEvent($db, 'unauthorized_tag', 'Intento de etiquetar publicación ajena: ' . $post_id, $uid);
                    flash('error', 'Solo el autor puede etiquetar');
                    header("Location: ./?r=posts/view&id=" . $post_id);
                    exit;
                }
                
                $tag_username = trim($_POST['tag_username'] ?? '');
                $x = floatval($_POST['x'] ?? 50);
                $y = floatval($_POST['y'] ?? 50);
                
                if (!empty($tag_username)) {
                    $user_stmt = $db->prepare("SELECT id FROM users WHERE username = ?");
                    $user_stmt->execute([$tag_username]);
                    $tagged_user = $user_stmt->fetch();
                    
                    if ($tagged_user) {
                        $check_stmt = $db->prepare("SELECT id FROM tags WHERE post_id = ? AND name = ?");
                        $check_stmt->execute([$post_id, $tag_username]);
                        
                        if (!$check_stmt->fetch()) {
                            $tag_stmt = $db->prepare("INSERT INTO tags (id, post_id, name, x, y) VALUES (?, ?, ?, ?, ?)");
                            $tag_id = self::generateUUID();
                            $tag_stmt->execute([$tag_id, $post_id, $tag_username, $x, $y]);
                            flash('success', 'Usuario etiquetado correctamente');
                            if ($tagged_user['id'] != $uid) {
                                self::notifyTag($db, $tagged_user['id'], $uid, $post_id);
                            }
                            SecurityHelper::logSecurityEvent($db, 'user_tagged', 'Usuario etiquetado: ' . $tag_username, $uid);
                        } else {
                            flash('info', 'El usuario ya está etiquetado en esta publicación');
                        }
                    } else {
                        flash('error', 'Usuario no encontrado');
                    }
                } else {
                    flash('error', 'Debes especificar un usuario');
                }
                
                header("Location: ./?r=posts/view&id=" . $post_id);
                exit;
            }
            
            if (isset($_POST['update_caption'])) {
                if (!$is_author && !$isAdmin) {
                    SecurityHelper::logSecurityEvent($db, 'unauthorized_edit', 'Intento de editar publicación ajena: ' . $post_id, $uid);
                    flash('error', 'Solo el autor puede editar la descripción');
                    header("Location: ./?r=posts/view&id=" . $post_id);
                    exit;
                }
                
                $new_caption = trim($_POST['caption'] ?? '');
                
                // Validar contenido malicioso
                if (self::containsMaliciousContent($new_caption)) {
                    SecurityHelper::logSecurityEvent($db, 'malicious_caption', 'Intento de edición con contenido malicioso', $uid);
                    flash('error', 'La descripción contiene texto no permitido.');
                    header("Location: ./?r=posts/view&id=" . $post_id);
                    exit;
                }
                
                if ($isAdmin) {
                    $update_stmt = $db->prepare("UPDATE posts SET caption = ? WHERE id = ?");
                    $update_stmt->execute([$new_caption, $post_id]);
                } else {
                    $update_stmt = $db->prepare("UPDATE posts SET caption = ? WHERE id = ? AND author_id = ?");
                    $update_stmt->execute([$new_caption, $post_id, $uid]);
                }
                
                if ($update_stmt->rowCount() > 0) {
                    SecurityHelper::logSecurityEvent($db, 'caption_updated', 'Descripción actualizada: ' . $post_id, $uid);
                    flash('success', 'Descripción actualizada correctamente');
                } else {
                    flash('error', 'Error al actualizar la descripción');
                }
                
                header("Location: ./?r=posts/view&id=" . $post_id);
                exit;
            }
        }
        
        view('posts/view', [
            'post' => $post,
            'photo' => $photo,
            'tags' => $tags,
            'comments' => $comments,
            'user_like' => ($post['is_liked'] ?? 0) > 0,
            'is_author' => $is_author,
            'isAdmin' => $isAdmin
        ]);
    }
    
    private static function notifyNewComment($db, $post_author_id, $commenter_id, $post_id) {
        $commenter_stmt = $db->prepare("SELECT username FROM users WHERE id = ?");
        $commenter_stmt->execute([$commenter_id]);
        $commenter = $commenter_stmt->fetch();
        
        $db->prepare("
            INSERT INTO notifications (id, user_id, type, related_user_id, related_post_id, message, created_at)
            VALUES (?, ?, 'comment', ?, ?, ?, NOW())
        ")->execute([
            self::generateUUID(),
            $post_author_id,
            $commenter_id,
            $post_id,
            $commenter['username'] . " comentó tu publicación"
        ]);
    }
    
    private static function notifyCommentReply($db, $comment_id, $replier_id, $post_id) {
        $comment_stmt = $db->prepare("SELECT user_id FROM comments WHERE id = ?");
        $comment_stmt->execute([$comment_id]);
        $comment = $comment_stmt->fetch();
        
        $replier_stmt = $db->prepare("SELECT username FROM users WHERE id = ?");
        $replier_stmt->execute([$replier_id]);
        $replier = $replier_stmt->fetch();
        
        if ($comment && $comment['user_id'] != $replier_id) {
            $db->prepare("
                INSERT INTO notifications (id, user_id, type, related_user_id, related_post_id, message, created_at)
                VALUES (?, ?, 'comment', ?, ?, ?, NOW())
            ")->execute([
                self::generateUUID(),
                $comment['user_id'],
                $replier_id,
                $post_id,
                $replier['username'] . " respondió a tu comentario"
            ]);
        }
    }
    
    private static function notifyTag($db, $tagged_user_id, $tagger_id, $post_id) {
        $tagger_stmt = $db->prepare("SELECT username FROM users WHERE id = ?");
        $tagger_stmt->execute([$tagger_id]);
        $tagger = $tagger_stmt->fetch();
        
        $db->prepare("
            INSERT INTO notifications (id, user_id, type, related_user_id, related_post_id, message, created_at)
            VALUES (?, ?, 'tag', ?, ?, ?, NOW())
        ")->execute([
            self::generateUUID(),
            $tagged_user_id,
            $tagger_id,
            $post_id,
            $tagger['username'] . " te etiquetó en una publicación"
        ]);
    }
    
    private static function notifyLike($db, $post_author_id, $liker_id, $post_id) {
        $liker_stmt = $db->prepare("SELECT username FROM users WHERE id = ?");
        $liker_stmt->execute([$liker_id]);
        $liker = $liker_stmt->fetch();
        
        $db->prepare("
            INSERT INTO notifications (id, user_id, type, related_user_id, related_post_id, message, created_at)
            VALUES (?, ?, 'like', ?, ?, ?, NOW())
        ")->execute([
            self::generateUUID(),
            $post_author_id,
            $liker_id,
            $post_id,
            $liker['username'] . " dio like a tu publicación"
        ]);
    }
    
    public static function delete($db) {
        require_login();
        $uid = $_SESSION['user']['id'];
        $post_id = $_GET['id'] ?? ($_POST['post_id'] ?? '');
        
        if (empty($post_id)) {
            flash('error', 'Publicación no válida');
            redirect('posts');
            return;
        }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            validate_csrf();
            
            $check_stmt = $db->prepare("SELECT author_id FROM posts WHERE id = ?");
            $check_stmt->execute([$post_id]);
            $post = $check_stmt->fetch();
            
            if (!$post || $post['author_id'] != $uid) {
                SecurityHelper::logSecurityEvent($db, 'unauthorized_delete_attempt', 'Intento de eliminar publicación ajena: ' . $post_id, $uid);
                flash('error', 'No tienes permiso para eliminar esta publicación');
                redirect('posts');
                return;
            }
            
            $db->beginTransaction();
            
            try {
                $photo_stmt = $db->prepare("SELECT url FROM photos WHERE post_id = ?");
                $photo_stmt->execute([$post_id]);
                $photo = $photo_stmt->fetch();
                
                $db->prepare("DELETE FROM tags WHERE post_id = ?")->execute([$post_id]);
                $db->prepare("DELETE FROM comments WHERE post_id = ?")->execute([$post_id]);
                $db->prepare("DELETE FROM likes WHERE post_id = ?")->execute([$post_id]);
                $db->prepare("DELETE FROM notifications WHERE related_post_id = ?")->execute([$post_id]);
                $db->prepare("DELETE FROM photos WHERE post_id = ?")->execute([$post_id]);
                $db->prepare("DELETE FROM posts WHERE id = ?")->execute([$post_id]);
                
                $db->commit();
                
                if ($photo && !empty($photo['url'])) {
                    global $CONFIG;
                    $file_path = str_replace($CONFIG['upload_url'], $CONFIG['upload_dir'], $photo['url']);
                    if (file_exists($file_path)) {
                        unlink($file_path);
                    }
                }
                
                SecurityHelper::logSecurityEvent($db, 'post_deleted', 'Publicación eliminada: ' . $post_id, $uid);
                flash('success', 'Publicación eliminada correctamente');
                
            } catch (Exception $e) {
                $db->rollBack();
                SecurityHelper::logSecurityEvent($db, 'post_deletion_error', 'Error al eliminar publicación: ' . $e->getMessage(), $uid);
                flash('error', 'Error al eliminar la publicación');
            }
        }
        
        redirect('posts');
    }
    
    public static function like($db) {
        require_login();
        $uid = $_SESSION['user']['id'];
        $post_id = $_GET['id'] ?? ($_POST['post_id'] ?? '');
        
        if (empty($post_id)) {
            echo json_encode(['success' => false, 'error' => 'Publicación no válida']);
            exit;
        }
        
        $check_stmt = $db->prepare("SELECT id FROM likes WHERE post_id = ? AND user_id = ?");
        $check_stmt->execute([$post_id, $uid]);
        
        if ($check_stmt->fetch()) {
            $delete_stmt = $db->prepare("DELETE FROM likes WHERE post_id = ? AND user_id = ?");
            $delete_stmt->execute([$post_id, $uid]);
            $liked = false;
            SecurityHelper::logSecurityEvent($db, 'post_unliked', 'Like eliminado: ' . $post_id, $uid);
        } else {
            $insert_stmt = $db->prepare("INSERT INTO likes (id, post_id, user_id, created_at) VALUES (?, ?, ?, NOW())");
            $like_id = self::generateUUID();
            $insert_stmt->execute([$like_id, $post_id, $uid]);
            $liked = true;
            SecurityHelper::logSecurityEvent($db, 'post_liked', 'Like añadido: ' . $post_id, $uid);
            
            $post_author_stmt = $db->prepare("SELECT author_id FROM posts WHERE id = ?");
            $post_author_stmt->execute([$post_id]);
            $post_author = $post_author_stmt->fetch();
            
            if ($post_author && $post_author['author_id'] != $uid) {
                self::notifyLike($db, $post_author['author_id'], $uid, $post_id);
            }
        }
        
        $count_stmt = $db->prepare("SELECT COUNT(*) as count FROM likes WHERE post_id = ?");
        $count_stmt->execute([$post_id]);
        $count = $count_stmt->fetch()['count'];
        
        echo json_encode(['success' => true, 'liked' => $liked, 'count' => $count]);
        exit;
    }

    public static function deleteTag($db) {
        require_login();
        $uid = $_SESSION['user']['id'];
        $tag_id = $_GET['id'] ?? '';
        
        if (empty($tag_id)) {
            flash('error', 'Etiqueta no válida');
            redirect('posts');
            return;
        }
        
        $check_stmt = $db->prepare("SELECT p.author_id, t.post_id FROM tags t JOIN posts p ON t.post_id = p.id WHERE t.id = ?");
        $check_stmt->execute([$tag_id]);
        $tag = $check_stmt->fetch();
        
        if (!$tag || $tag['author_id'] != $uid) {
            SecurityHelper::logSecurityEvent($db, 'unauthorized_tag_delete', 'Intento de eliminar etiqueta ajena: ' . $tag_id, $uid);
            flash('error', 'No tienes permiso para eliminar esta etiqueta');
            redirect('posts');
            return;
        }
        
        $delete_stmt = $db->prepare("DELETE FROM tags WHERE id = ?");
        $success = $delete_stmt->execute([$tag_id]);
        
        if ($success) {
            SecurityHelper::logSecurityEvent($db, 'tag_deleted', 'Etiqueta eliminada: ' . $tag_id, $uid);
            flash('success', 'Etiqueta eliminada correctamente');
        } else {
            flash('error', 'Error al eliminar la etiqueta');
        }
        
        $post_id = $tag['post_id'] ?? '';
        if (!empty($post_id)) {
            header("Location: ./?r=posts/view&id=" . $post_id);
            exit;
        } else {
            redirect('posts');
        }
    }
    
    public static function deleteComment($db) {
        require_login();
        $uid = $_SESSION['user']['id'];
        $comment_id = $_GET['id'] ?? '';
        
        if (empty($comment_id)) {
            flash('error', 'Comentario no válido');
            redirect('posts');
            return;
        }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            validate_csrf();
            
            $check_stmt = $db->prepare("
                SELECT c.*, p.author_id as post_author_id, p.id as post_id 
                FROM comments c 
                JOIN posts p ON c.post_id = p.id 
                WHERE c.id = ? AND (c.user_id = ? OR p.author_id = ?)
            ");
            $check_stmt->execute([$comment_id, $uid, $uid]);
            $comment_to_delete = $check_stmt->fetch();
            
            if (!$comment_to_delete) {
                SecurityHelper::logSecurityEvent($db, 'unauthorized_comment_delete', 'Intento de eliminar comentario ajeno: ' . $comment_id, $uid);
                flash('error', 'No tienes permiso para eliminar este comentario');
                redirect('posts');
                return;
            }
            
            try {
                $delete_stmt = $db->prepare("DELETE FROM comments WHERE id = ? OR reply_to = ?");
                $success = $delete_stmt->execute([$comment_id, $comment_id]);
                
                if ($success) {
                    SecurityHelper::logSecurityEvent($db, 'comment_deleted', 'Comentario eliminado: ' . $comment_id, $uid);
                    flash('success', 'Comentario eliminado correctamente');
                } else {
                    flash('error', 'Error al eliminar el comentario');
                }
            } catch (Exception $e) {
                error_log("Error al eliminar comentario: " . $e->getMessage());
                SecurityHelper::logSecurityEvent($db, 'comment_deletion_error', 'Error al eliminar comentario: ' . $e->getMessage(), $uid);
                flash('error', 'Error del sistema al eliminar el comentario');
            }
            
            header("Location: ./?r=posts/view&id=" . $comment_to_delete['post_id']);
            exit;
        }
        
        redirect('posts');
    }
    
    public static function updateCaption($db) {
        require_login();
        $uid = $_SESSION['user']['id'];
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            validate_csrf();
            
            $post_id = $_POST['post_id'] ?? '';
            $caption = trim($_POST['caption'] ?? '');
            
            if (empty($post_id)) {
                flash('error', 'Publicación no válida');
                redirect('posts');
                return;
            }
            
            $check_stmt = $db->prepare("SELECT author_id FROM posts WHERE id = ?");
            $check_stmt->execute([$post_id]);
            $post = $check_stmt->fetch();
            
            if (!$post || $post['author_id'] != $uid) {
                SecurityHelper::logSecurityEvent($db, 'unauthorized_edit', 'Intento de editar publicación ajena: ' . $post_id, $uid);
                flash('error', 'No tienes permiso para editar esta publicación');
                redirect('posts');
                return;
            }
            
            // Validar contenido malicioso
            if (self::containsMaliciousContent($caption)) {
                SecurityHelper::logSecurityEvent($db, 'malicious_caption', 'Intento de edición con contenido malicioso', $uid);
                flash('error', 'La descripción contiene texto no permitido.');
                redirect('posts/view?id=' . $post_id);
                return;
            }
            
            $update_stmt = $db->prepare("UPDATE posts SET caption = ? WHERE id = ?");
            $success = $update_stmt->execute([$caption, $post_id]);
            
            if ($success) {
                SecurityHelper::logSecurityEvent($db, 'caption_updated', 'Descripción actualizada: ' . $post_id, $uid);
                flash('success', 'Descripción actualizada correctamente');
            } else {
                flash('error', 'Error al actualizar la descripción');
            }
            
            header("Location: ./?r=posts/view&id=" . $post_id);
            exit;
        }
    }
    
    private static function containsMaliciousContent($text) {
        // Lista de patrones maliciosos
        $malicious_patterns = [
            '/<script.*?>.*?<\/script>/si',
            '/javascript:/i',
            '/onload=/i',
            '/onerror=/i',
            '/onclick=/i',
            '/eval\(/i',
            '/alert\(/i',
            '/document\.cookie/i',
            '/window\.location/i',
            '/base64_decode/i',
            '/fromCharCode/i',
            '/<iframe.*?>.*?<\/iframe>/si',
            '/<meta.*?>.*?<\/meta>/si',
            '/<link.*?>.*?<\/link>/si',
            '/<object.*?>.*?<\/object>/si',
            '/<embed.*?>.*?<\/embed>/si',
            '/<applet.*?>.*?<\/applet>/si',
        ];
        
        foreach ($malicious_patterns as $pattern) {
            if (preg_match($pattern, $text)) {
                return true;
            }
        }
        
        return false;
    }
}