T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/soundstudiopro.com/private_html/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/soundstudiopro.com/private_html/notifications.php
<?php
session_start();

// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
    header('Location: /auth/login.php');
    exit;
}

require_once 'config/database.php';
require_once 'includes/translations.php';
$pdo = getDBConnection();

$user_id = $_SESSION['user_id'];

// Set page variables for header
$page_title = t('notifications.page_title');
$page_description = t('notifications.page_description');
$current_page = 'notifications';

// Get user info
$stmt = $pdo->prepare("SELECT name FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();

// Get notification counts for display
$friend_requests_count = 0;
$likes_count = 0;
$comments_count = 0;
$artist_ratings_count = 0;
$track_ratings_count = 0;
$follows_count = 0;
$total_notification_count = 0;

// Create notification_reads table if it doesn't exist
try {
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS notification_reads (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL,
            notification_type ENUM('friend_request', 'like', 'comment', 'artist_rating', 'track_rating', 'follow') NOT NULL,
            notification_id INT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            UNIQUE KEY unique_notification (user_id, notification_type, notification_id),
            FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
            INDEX idx_user_type (user_id, notification_type)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
} catch (PDOException $e) {
    // Table might already exist, that's okay
}

// Create notification_clear_state table and get last cleared timestamp
$last_cleared_at = null;
try {
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS notification_clear_state (
            user_id INT PRIMARY KEY,
            last_cleared_at TIMESTAMP NULL DEFAULT NULL,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
    
    $stmt = $pdo->prepare("SELECT last_cleared_at FROM notification_clear_state WHERE user_id = ?");
    $stmt->execute([$user_id]);
    $last_cleared_at = $stmt->fetchColumn() ?: null;
} catch (PDOException $e) {
    error_log("Error preparing notification_clear_state: " . $e->getMessage());
}

$cleared_param = $last_cleared_at;

try {
    // Count unread friend requests (excluding read ones)
    $stmt = $pdo->prepare("
        SELECT COUNT(*) 
        FROM user_friends uf
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'friend_request' AND nr.notification_id = uf.id
        WHERE uf.friend_id = ? AND uf.status = 'pending' AND nr.id IS NULL
        AND (? IS NULL OR uf.created_at > ?)
    ");
    $stmt->execute([$user_id, $user_id, $cleared_param, $cleared_param]);
    $friend_requests_count = (int)$stmt->fetchColumn();
    
    // Count unread likes on user's tracks (excluding user's own likes and read ones)
    $stmt = $pdo->prepare("
        SELECT COUNT(*) 
        FROM track_likes tl 
        JOIN music_tracks mt ON tl.track_id = mt.id 
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'like' AND nr.notification_id = tl.id
        WHERE mt.user_id = ? AND tl.user_id != ? AND nr.id IS NULL
        AND (? IS NULL OR tl.created_at > ?)
    ");
    $stmt->execute([$user_id, $user_id, $user_id, $cleared_param, $cleared_param]);
    $likes_count = (int)$stmt->fetchColumn();
    
    // Count unread comments on user's tracks (excluding user's own comments and read ones)
    $stmt = $pdo->prepare("
        SELECT COUNT(*) 
        FROM track_comments tc 
        JOIN music_tracks mt ON tc.track_id = mt.id 
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'comment' AND nr.notification_id = tc.id
        WHERE mt.user_id = ? AND tc.user_id != ? AND nr.id IS NULL
        AND (? IS NULL OR tc.created_at > ?)
    ");
    $stmt->execute([$user_id, $user_id, $user_id, $cleared_param, $cleared_param]);
    $comments_count = (int)$stmt->fetchColumn();
    
    // Count unread artist ratings
    $stmt = $pdo->prepare("
        SELECT COUNT(*) 
        FROM artist_ratings ar
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'artist_rating' AND nr.notification_id = ar.id
        WHERE ar.artist_id = ? AND ar.user_id != ? AND nr.id IS NULL
        AND (? IS NULL OR ar.updated_at > ?)
    ");
    $stmt->execute([$user_id, $user_id, $user_id, $cleared_param, $cleared_param]);
    $artist_ratings_count = (int)$stmt->fetchColumn();
    
    // Count unread track ratings
    $stmt = $pdo->prepare("
        SELECT COUNT(*) 
        FROM track_ratings tr
        JOIN music_tracks mt ON tr.track_id = mt.id 
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'track_rating' AND nr.notification_id = tr.id
        WHERE mt.user_id = ? AND tr.user_id != ? AND nr.id IS NULL
        AND (? IS NULL OR tr.updated_at > ?)
    ");
    $stmt->execute([$user_id, $user_id, $user_id, $cleared_param, $cleared_param]);
    $track_ratings_count = (int)$stmt->fetchColumn();
    
    // Count unread follows
    $stmt = $pdo->prepare("
        SELECT COUNT(*) 
        FROM user_follows uf
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'follow' AND nr.notification_id = uf.id
        WHERE uf.following_id = ? AND uf.follower_id != ? AND nr.id IS NULL
        AND (? IS NULL OR uf.created_at > ?)
    ");
    $stmt->execute([$user_id, $user_id, $user_id, $cleared_param, $cleared_param]);
    $follows_count = (int)$stmt->fetchColumn();
    
    // Get purchase notifications count
    $purchase_notifications_count = 0;
    try {
        require_once __DIR__ . '/utils/artist_notifications.php';
        $purchase_notifications_count = getArtistPurchaseNotificationsCount($user_id);
    } catch (Exception $e) {
        error_log("Error counting purchase notifications: " . $e->getMessage());
    }
    
    // Get ticket sale notifications count
    $ticket_notifications_count = 0;
    try {
        require_once __DIR__ . '/utils/artist_notifications.php';
        $ticket_notifications_count = getOrganizerTicketNotificationsCount($user_id);
    } catch (Exception $e) {
        error_log("Error counting ticket notifications: " . $e->getMessage());
    }
    
    $total_notification_count = $friend_requests_count + $likes_count + $comments_count + $artist_ratings_count + $track_ratings_count + $follows_count + $purchase_notifications_count + $ticket_notifications_count;
} catch (PDOException $e) {
    error_log("Error counting notifications: " . $e->getMessage());
}

// Ensure artist_purchase_notifications table exists before querying
try {
    // First check if table exists
    $table_check = $pdo->query("SHOW TABLES LIKE 'artist_purchase_notifications'");
    if ($table_check->rowCount() === 0) {
        // Try to create table without foreign keys first (they can be added later if needed)
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS artist_purchase_notifications (
                id INT AUTO_INCREMENT PRIMARY KEY,
                artist_id INT NOT NULL,
                track_id INT NOT NULL,
                buyer_id INT NOT NULL,
                purchase_id INT NOT NULL,
                price_paid DECIMAL(10,2) NOT NULL,
                is_read TINYINT(1) DEFAULT 0,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_artist_read (artist_id, is_read),
                INDEX idx_created_at (created_at),
                INDEX idx_artist_id (artist_id),
                INDEX idx_track_id (track_id),
                INDEX idx_buyer_id (buyer_id)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
        ");
    }
} catch (PDOException $e) {
    // Table might already exist or creation might fail, that's okay
    error_log("Could not create artist_purchase_notifications table: " . $e->getMessage());
}

// Get notifications (including read ones for display, but we'll show unread status)
try {
    // Check if artist_purchase_notifications table exists
    $table_exists = false;
    try {
        $table_check = $pdo->query("SHOW TABLES LIKE 'artist_purchase_notifications'");
        $table_exists = $table_check->rowCount() > 0;
    } catch (PDOException $e) {
        error_log("Error checking for artist_purchase_notifications table: " . $e->getMessage());
    }
    
    // Check if event_ticket_notifications table exists
    $ticket_table_exists = false;
    try {
        $table_check = $pdo->query("SHOW TABLES LIKE 'event_ticket_notifications'");
        $ticket_table_exists = $table_check->rowCount() > 0;
    } catch (PDOException $e) {
        error_log("Error checking for event_ticket_notifications table: " . $e->getMessage());
    }
    
    $stmt = $pdo->prepare("
        SELECT 
            'friend_request' as type,
            uf.created_at as created_at,
            UNIX_TIMESTAMP(uf.created_at) as created_at_timestamp,
            u.name as sender_name,
            u.name as sender_username,
            u.id as sender_id,
            NULL as track_id,
            NULL as track_title,
            '' as message,
            uf.id as notification_id,
            CASE WHEN nr.id IS NULL THEN 0 ELSE 1 END as is_read,
            NULL as rating_value,
            NULL as rating_comment
        FROM user_friends uf
        JOIN users u ON uf.user_id = u.id
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'friend_request' AND nr.notification_id = uf.id
        WHERE uf.friend_id = ? AND uf.status = 'pending'
        
        UNION ALL
        
        SELECT 
            'like' as type,
            tl.created_at as created_at,
            UNIX_TIMESTAMP(tl.created_at) as created_at_timestamp,
            u.name as sender_name,
            u.name as sender_username,
            tl.user_id as sender_id,
            mt.id as track_id,
            mt.title as track_title,
            '' as message,
            tl.id as notification_id,
            CASE WHEN nr.id IS NULL THEN 0 ELSE 1 END as is_read,
            NULL as rating_value,
            NULL as rating_comment
        FROM track_likes tl
        JOIN users u ON tl.user_id = u.id
        JOIN music_tracks mt ON tl.track_id = mt.id
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'like' AND nr.notification_id = tl.id
        WHERE mt.user_id = ? AND tl.user_id != ?
        
        UNION ALL
        
        SELECT 
            'comment' as type,
            tc.created_at as created_at,
            UNIX_TIMESTAMP(tc.created_at) as created_at_timestamp,
            u.name as sender_name,
            u.name as sender_username,
            tc.user_id as sender_id,
            mt.id as track_id,
            mt.title as track_title,
            '' as message,
            tc.id as notification_id,
            CASE WHEN nr.id IS NULL THEN 0 ELSE 1 END as is_read,
            NULL as rating_value,
            NULL as rating_comment
        FROM track_comments tc
        JOIN users u ON tc.user_id = u.id
        JOIN music_tracks mt ON tc.track_id = mt.id
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'comment' AND nr.notification_id = tc.id
        WHERE mt.user_id = ? AND tc.user_id != ?
        
        UNION ALL
        
        SELECT 
            'artist_rating' as type,
            ar.updated_at as created_at,
            UNIX_TIMESTAMP(ar.updated_at) as created_at_timestamp,
            u.name as sender_name,
            u.name as sender_username,
            ar.user_id as sender_id,
            NULL as track_id,
            NULL as track_title,
            '' as message,
            ar.id as notification_id,
            CASE WHEN nr.id IS NULL THEN 0 ELSE 1 END as is_read,
            ar.rating as rating_value,
            ar.comment as rating_comment
        FROM artist_ratings ar
        JOIN users u ON ar.user_id = u.id
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'artist_rating' AND nr.notification_id = ar.id
        WHERE ar.artist_id = ? AND ar.user_id != ?
        
        UNION ALL
        
        SELECT 
            'track_rating' as type,
            tr.updated_at as created_at,
            UNIX_TIMESTAMP(tr.updated_at) as created_at_timestamp,
            u.name as sender_name,
            u.name as sender_username,
            tr.user_id as sender_id,
            mt.id as track_id,
            mt.title as track_title,
            '' as message,
            tr.id as notification_id,
            CASE WHEN nr.id IS NULL THEN 0 ELSE 1 END as is_read,
            tr.rating as rating_value,
            tr.comment as rating_comment
        FROM track_ratings tr
        JOIN users u ON tr.user_id = u.id
        JOIN music_tracks mt ON tr.track_id = mt.id
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'track_rating' AND nr.notification_id = tr.id
        WHERE mt.user_id = ? AND tr.user_id != ?
        
        UNION ALL
        
        SELECT 
            'follow' as type,
            uf.created_at as created_at,
            UNIX_TIMESTAMP(uf.created_at) as created_at_timestamp,
            u.name as sender_name,
            u.name as sender_username,
            uf.follower_id as sender_id,
            NULL as track_id,
            NULL as track_title,
            '' as message,
            uf.id as notification_id,
            CASE WHEN nr.id IS NULL THEN 0 ELSE 1 END as is_read,
            NULL as rating_value,
            NULL as rating_comment
        FROM user_follows uf
        JOIN users u ON uf.follower_id = u.id
        LEFT JOIN notification_reads nr ON nr.user_id = ? AND nr.notification_type = 'follow' AND nr.notification_id = uf.id
        WHERE uf.following_id = ? AND uf.follower_id != ?
        " . ($table_exists ? "
        UNION ALL
        
        SELECT 
            'track_purchase' as type,
            apn.created_at as created_at,
            UNIX_TIMESTAMP(apn.created_at) as created_at_timestamp,
            u.name as sender_name,
            u.name as sender_username,
            apn.buyer_id as sender_id,
            mt.id as track_id,
            mt.title as track_title,
            FORMAT(apn.price_paid, 2) as message,
            apn.id as notification_id,
            CASE WHEN apn.is_read = 0 THEN 0 ELSE 1 END as is_read,
            NULL as rating_value,
            NULL as rating_comment
        FROM artist_purchase_notifications apn
        JOIN users u ON apn.buyer_id = u.id
        JOIN music_tracks mt ON apn.track_id = mt.id
        WHERE apn.artist_id = ?
        " : "") . ($ticket_table_exists ? "
        UNION ALL
        
        SELECT 
            'ticket_sale' as type,
            etn.created_at as created_at,
            UNIX_TIMESTAMP(etn.created_at) as created_at_timestamp,
            u.name as sender_name,
            u.name as sender_username,
            etn.buyer_id as sender_id,
            NULL as track_id,
            e.title as track_title,
            e.id as event_id,
            CONCAT(FORMAT(etn.price_paid, 2), ' x', etn.quantity) as message,
            etn.id as notification_id,
            CASE WHEN etn.is_read = 0 THEN 0 ELSE 1 END as is_read,
            NULL as rating_value,
            NULL as rating_comment
        FROM event_ticket_notifications etn
        JOIN users u ON etn.buyer_id = u.id
        JOIN events e ON etn.event_id = e.id
        WHERE etn.organizer_id = ?
        " : "") . "
        ORDER BY created_at DESC
        LIMIT 100
    ");
    
    $execute_params = [
        $user_id, $user_id, // friend requests
        $user_id, $user_id, $user_id, // likes
        $user_id, $user_id, $user_id, // comments
        $user_id, $user_id, $user_id, // artist ratings
        $user_id, $user_id, $user_id, // track ratings
        $user_id, $user_id, $user_id  // follows
    ];
    
    if ($table_exists) {
        $execute_params[] = $user_id; // track purchases
    }
    
    if ($ticket_table_exists) {
        $execute_params[] = $user_id; // ticket sales
    }
    
    $stmt->execute($execute_params);
    $notifications = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Translate notification messages (keep track title separate for display)
    foreach ($notifications as &$notification) {
        if (isset($notification['rating_value']) && $notification['rating_value'] !== null) {
            $notification['rating_value_display'] = number_format((float)$notification['rating_value'], 1);
        }
        if ($notification['type'] === 'friend_request') {
            $notification['message'] = t('notifications.sent_friend_request');
        } elseif ($notification['type'] === 'like') {
            $notification['message'] = t('notifications.liked_track');
        } elseif ($notification['type'] === 'comment') {
            $notification['message'] = t('notifications.commented_track');
        } elseif ($notification['type'] === 'artist_rating') {
            $ratingText = $notification['rating_value_display'] ?? number_format((float)($notification['rating_value'] ?? 0), 1);
            $notification['message'] = str_replace(':rating', $ratingText, t('notifications.artist_rating_message'));
        } elseif ($notification['type'] === 'track_rating') {
            $ratingText = $notification['rating_value_display'] ?? number_format((float)($notification['rating_value'] ?? 0), 1);
            $titleText = $notification['track_title'] ?: t('notifications.untitled_track');
            // Store raw title for link creation in display
            $notification['track_title_raw'] = $titleText;
            $notification['message'] = str_replace(
                [':rating', ':title'],
                [$ratingText, $titleText],
                t('notifications.track_rating_message')
            );
        } elseif ($notification['type'] === 'track_purchase') {
            // Store raw price before formatting message (message contains formatted price from SQL)
            $notification['price_raw'] = $notification['message'] ?? '0.00';
            $notification['earnings_link'] = '/artist_dashboard.php?tab=earnings';
            // Don't format message here - we'll format it in display with track link
        } elseif ($notification['type'] === 'follow') {
            $notification['message'] = t('notifications.started_following');
        } elseif ($notification['type'] === 'ticket_sale') {
            // Store raw price and quantity before formatting message
            $event_title = htmlspecialchars($notification['track_title'] ?? t('notifications.untitled_event'));
            $buyer_name = htmlspecialchars($notification['sender_name'] ?? t('notifications.anonymous_buyer'));
            $price_info = $notification['message'] ?? '0.00 x1';
            $notification['price_raw'] = $price_info;
            $notification['earnings_link'] = '/event_sales_earnings.php?event_id=' . ($notification['event_id'] ?? '');
            // Don't format message here - we'll format it in display with event link
        }
        
        if ($last_cleared_at && isset($notification['created_at'])) {
            $cleared_ts = strtotime($last_cleared_at);
            $notification_ts = strtotime($notification['created_at']);
            if ($cleared_ts && $notification_ts && $notification_ts <= $cleared_ts) {
                $notification['is_read'] = 1;
            }
        }
    }
    unset($notification); // Break the reference
} catch (PDOException $e) {
    error_log("Database error in notifications.php: " . $e->getMessage());
    $notifications = [];
    $error_message = t('notifications.unable_to_load');
}

include 'includes/header.php';
?>

<div class="main-content">
    <div class="container">
        <div class="page-header">
            <div class="page-header-content">
                <div class="page-title-section">
                    <h1 class="page-title">
                        <i class="fas fa-bell"></i>
                        <?= t('notifications.title') ?>
                        <?php if ($total_notification_count > 0): ?>
                            <span class="notification-count-badge"><?= $total_notification_count ?></span>
                        <?php endif; ?>
                    </h1>
                    <p class="page-subtitle">
                        <?php if ($total_notification_count > 0): ?>
                            <?= t($total_notification_count > 1 ? 'notifications.you_have_plural' : 'notifications.you_have', ['count' => $total_notification_count]) ?>
                            (<?= $friend_requests_count ?> <?= t($friend_requests_count != 1 ? 'notifications.friend_request_plural' : 'notifications.friend_request') ?>, 
                             <?= $likes_count ?> <?= t($likes_count != 1 ? 'notifications.like_plural' : 'notifications.like') ?>, 
                             <?= $comments_count ?> <?= t($comments_count != 1 ? 'notifications.comment_plural' : 'notifications.comment') ?>,
                             <?= $artist_ratings_count ?> <?= t($artist_ratings_count != 1 ? 'notifications.artist_rating_plural' : 'notifications.artist_rating') ?>,
                             <?= $track_ratings_count ?> <?= t($track_ratings_count != 1 ? 'notifications.track_rating_plural' : 'notifications.track_rating') ?>,
                             <?= $follows_count ?> <?= t($follows_count != 1 ? 'notifications.follow_plural' : 'notifications.follow') ?>)
                        <?php else: ?>
                            <?= t('notifications.stay_updated') ?>
                        <?php endif; ?>
                    </p>
                </div>
                <div class="page-actions">
                    <?php if ($total_notification_count > 0): ?>
                        <button onclick="markAllAsRead()" class="btn btn-primary" id="markAllReadBtn">
                            <i class="fas fa-check-double"></i>
                            <?= t('notifications.mark_all_read') ?>
                        </button>
                    <?php endif; ?>
                    <a href="/dashboard.php" class="btn btn-ghost" target="_blank">
                        <i class="fas fa-arrow-left"></i>
                        <?= t('notifications.back_to_dashboard') ?>
                    </a>
                </div>
            </div>
        </div>

        <div class="notifications-section">
            <?php if (isset($error_message)): ?>
                <div class="error-card">
                    <div class="error-content">
                        <i class="fas fa-exclamation-triangle"></i>
                        <h3><?= t('notifications.error_loading') ?></h3>
                        <p><?= htmlspecialchars($error_message) ?></p>
                        <button onclick="location.reload()" class="btn btn-primary">
                            <i class="fas fa-refresh"></i> <?= t('notifications.try_again') ?>
                        </button>
                    </div>
                </div>
            <?php elseif (empty($notifications)): ?>
                <div class="empty-state">
                    <div class="empty-state-content">
                        <i class="fas fa-bell-slash"></i>
                        <h3><?= t('notifications.no_notifications') ?></h3>
                        <p><?= t('notifications.no_notifications_desc') ?></p>
                        <div class="empty-state-actions">
                            <a href="/community_fixed.php" class="btn btn-primary" target="_blank">
                                <i class="fas fa-users"></i>
                                <?= t('notifications.explore_community') ?>
                            </a>
                            <a href="/charts.php" class="btn btn-secondary" target="_blank">
                                <i class="fas fa-chart-line"></i>
                                <?= t('notifications.view_charts') ?>
                            </a>
                        </div>
                    </div>
                </div>
            <?php else: ?>
                <div class="notifications-grid">
                    <?php foreach ($notifications as $notification): ?>
                        <div class="notification-card <?= isset($notification['is_read']) && $notification['is_read'] ? 'read' : 'unread' ?>" data-type="<?= $notification['type'] ?>" data-sender-id="<?= $notification['sender_id'] ?>">
                            <div class="notification-avatar">
                                <?= strtoupper(substr($notification['sender_name'], 0, 1)) ?>
                            </div>
                            
                            <div class="notification-content">
                                <div class="notification-header">
                                    <a href="/artist_profile.php?id=<?= $notification['sender_id'] ?>" class="sender-name" target="_blank">
                                        <?= htmlspecialchars($notification['sender_name']) ?>
                                    </a>
                                    <span class="notification-time">
                                        <?= timeAgo($notification['created_at'], $notification['created_at_timestamp'] ?? null) ?>
                                    </span>
                                </div>
                                
                                <div class="notification-message">
                                    <i class="fas fa-<?= getNotificationIcon($notification['type']) ?> notification-type-icon <?= $notification['type'] ?>"></i>
                                    <?php if ($notification['type'] === 'track_purchase'): ?>
                                        <?php
                                        // Extract track title and make it a link
                                        $track_title = htmlspecialchars($notification['track_title'] ?? t('notifications.untitled_track'));
                                        $buyer_name = htmlspecialchars($notification['sender_name'] ?? t('notifications.anonymous_buyer'));
                                        $price = $notification['price_raw'] ?? $notification['message'] ?? '0.00';
                                        
                                        // Build message with track title as link
                                        $message_template = t('notifications.track_purchased_message');
                                        $track_link = '<a href="/track.php?id=' . $notification['track_id'] . '" class="track-link" target="_blank" style="display:inline !important;">' . $track_title . '</a>';
                                        $message = str_replace(
                                            [':track', ':buyer', ':price'],
                                            ['"' . $track_link . '"', $buyer_name, $price],
                                            $message_template
                                        );
                                        echo '<span style="display:inline;">' . $message . '</span>';
                                        ?>
                                    <?php elseif ($notification['type'] === 'ticket_sale'): ?>
                                        <?php
                                        // Extract event title and make it a link
                                        $event_title = htmlspecialchars($notification['track_title'] ?? t('notifications.untitled_event'));
                                        $buyer_name = htmlspecialchars($notification['sender_name'] ?? t('notifications.anonymous_buyer'));
                                        $price_info = $notification['price_raw'] ?? $notification['message'] ?? '0.00 x1';
                                        
                                        // Parse price and quantity
                                        if (preg_match('/([\d.]+)\s*x(\d+)/', $price_info, $matches)) {
                                            $price = '$' . $matches[1];
                                            $quantity = $matches[2];
                                        } else {
                                            $price = '$' . $price_info;
                                            $quantity = '1';
                                        }
                                        
                                        // Build message with event title as link
                                        $message_template = t('notifications.ticket_sold_message');
                                        $event_link = '<a href="/events.php?event=' . ($notification['event_id'] ?? '') . '" class="track-link" target="_blank" style="display:inline !important;">' . $event_title . '</a>';
                                        $message = str_replace(
                                            [':event', ':buyer', ':price', ':quantity'],
                                            [$event_link, $buyer_name, $price, $quantity],
                                            $message_template
                                        );
                                        echo $message;
                                        ?>
                                    <?php elseif ($notification['type'] === 'track_rating' && isset($notification['track_id'])): ?>
                                        <?php
                                        // Build message with track title as link (no rating in message, only in pill)
                                        $track_title = htmlspecialchars($notification['track_title_raw'] ?? $notification['track_title'] ?? t('notifications.untitled_track'));
                                        $message_template = t('notifications.track_rating_message');
                                        $track_link = '<a href="/track.php?id=' . $notification['track_id'] . '" class="track-link" target="_blank" style="display:inline !important;">' . $track_title . '</a>';
                                        $message = str_replace(
                                            ':title',
                                            '"' . $track_link . '"',
                                            $message_template
                                        );
                                        echo '<span style="display:inline;">' . $message . '</span>';
                                        ?>
                                    <?php elseif (in_array($notification['type'], ['like', 'comment']) && isset($notification['track_id'])): ?>
                                        <?= htmlspecialchars($notification['message']) ?> 
                                        <a href="/track.php?id=<?= $notification['track_id'] ?>" class="track-link" target="_blank">
                                            "<?= htmlspecialchars($notification['track_title'] ?: 'Untitled') ?>"
                                        </a>
                                    <?php else: ?>
                                        <?= htmlspecialchars($notification['message']) ?>
                                    <?php endif; ?>
                                    <?php if (!empty($notification['rating_value_display'])): ?>
                                        <span class="rating-pill"><?= $notification['rating_value_display'] ?>/10</span>
                                    <?php endif; ?>
                                </div>
                                
                                <?php if (in_array($notification['type'], ['artist_rating', 'track_rating']) && !empty($notification['rating_comment'])): ?>
                                    <div class="notification-rating-comment">
                                        “<?= htmlspecialchars($notification['rating_comment']) ?>”
                                    </div>
                                <?php endif; ?>
                                
                                <div class="notification-actions">
                                    <?php if ($notification['type'] === 'friend_request'): ?>
                                        <button class="btn btn-success btn-sm" onclick="acceptFriend(<?= $notification['sender_id'] ?>, this)">
                                            <i class="fas fa-check"></i> <?= t('notifications.accept') ?>
                                        </button>
                                        <button class="btn btn-danger btn-sm" onclick="declineFriend(<?= $notification['sender_id'] ?>, this)">
                                            <i class="fas fa-times"></i> <?= t('notifications.decline') ?>
                                        </button>
                                    <?php elseif (in_array($notification['type'], ['track_purchase', 'ticket_sale']) && isset($notification['earnings_link'])): ?>
                                        <a href="<?= $notification['earnings_link'] ?>" class="btn btn-primary btn-sm" target="_blank">
                                            <i class="fas fa-dollar-sign"></i> <?= t('notifications.view_earnings') ?>
                                        </a>
                                    <?php else: ?>
                                        <button class="btn btn-primary btn-sm" onclick="viewProfile(<?= $notification['sender_id'] ?>)">
                                            <i class="fas fa-user"></i> <?= t('notifications.view_profile') ?>
                                        </button>
                                    <?php endif; ?>
                                </div>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>
            <?php endif; ?>
        </div>
    </div>
</div>

<style>
    /* Notifications Page Styles */
    .page-header {
        background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1));
        border-radius: 12px;
        padding: 2rem;
        margin-bottom: 2rem;
        border: 1px solid rgba(102, 126, 234, 0.2);
        backdrop-filter: blur(10px);
    }
    
    .page-header-content {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 1.5rem;
    }
    
    .page-title-section {
        flex: 1;
    }
    
    .page-title {
        font-size: 2.4rem;
        font-weight: 700;
        color: white;
        margin-bottom: 0.3rem;
        display: flex;
        align-items: center;
        gap: 0.8rem;
    }
    
    .page-title i {
        color: #667eea;
        font-size: 2rem;
    }
    
    .notification-count-badge {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: linear-gradient(135deg, #667eea, #764ba2);
        color: white;
        font-size: 1.4rem;
        font-weight: 700;
        padding: 0.3rem 0.8rem;
        border-radius: 20px;
        margin-left: 1rem;
        min-width: 2.5rem;
        height: 2.5rem;
        box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
        animation: notificationPulse 2s infinite;
    }
    
    @keyframes notificationPulse {
        0%, 100% {
            transform: scale(1);
            box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
        }
        50% {
            transform: scale(1.05);
            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.5);
        }
    }
    
    .page-subtitle {
        font-size: 1.4rem;
        color: rgba(255, 255, 255, 0.8);
        font-weight: 400;
    }
    
    .page-actions {
        display: flex;
        gap: 1rem;
    }
    
    .notifications-section {
        margin-bottom: 3rem;
    }
    
    .notifications-grid {
        display: flex;
        flex-direction: column;
        gap: 1rem;
    }
    
    .notification-card {
        background: rgba(255, 255, 255, 0.05);
        border: 1px solid rgba(255, 255, 255, 0.1);
        border-radius: 12px;
        padding: 1.5rem;
        display: flex;
        align-items: flex-start;
        gap: 1.2rem;
        transition: all 0.3s ease;
        backdrop-filter: blur(10px);
    }
    
    .notification-card:hover {
        background: rgba(255, 255, 255, 0.08);
        border-color: rgba(102, 126, 234, 0.3);
        transform: translateY(-1px);
        box-shadow: 0 4px 15px rgba(102, 126, 234, 0.15);
    }
    
    .notification-card.unread {
        border-left: 4px solid #667eea;
        background: rgba(102, 126, 234, 0.08);
    }
    
    .notification-card.read {
        opacity: 0.7;
    }
    
    .notification-avatar {
        width: 4rem;
        height: 4rem;
        border-radius: 50%;
        background: linear-gradient(135deg, #667eea, #764ba2);
        display: flex;
        align-items: center;
        justify-content: center;
        color: white;
        font-weight: 700;
        font-size: 1.4rem;
        flex-shrink: 0;
        border: 2px solid rgba(255, 255, 255, 0.1);
    }
    
    .notification-content {
        flex: 1;
        min-width: 0;
    }
    
    .notification-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 0.8rem;
        flex-wrap: wrap;
        gap: 1rem;
    }
    
    .sender-name {
        font-weight: 600;
        color: white;
        text-decoration: none;
        font-size: 1.4rem;
        transition: color 0.3s ease;
    }
    
    .sender-name:hover {
        color: #667eea;
    }
    
    .notification-time {
        font-size: 1.1rem;
        color: rgba(255, 255, 255, 0.6);
        font-weight: 400;
    }
    
    .notification-message {
        color: rgba(255, 255, 255, 0.9);
        line-height: 1.5;
        font-size: 1.3rem;
        margin-bottom: 1rem;
        display: flex;
        align-items: center;
        gap: 0.6rem;
        flex-wrap: wrap;
    }
    
    .notification-message .track-link {
        display: inline !important;
        white-space: nowrap;
    }
    
    .rating-pill {
        display: inline-flex;
        align-items: center;
        padding: 0.2rem 0.6rem;
        border-radius: 999px;
        background: rgba(250, 204, 21, 0.15);
        color: #facc15;
        font-weight: 700;
        font-size: 1.2rem;
    }
    
    .notification-rating-comment {
        margin-top: -0.5rem;
        margin-bottom: 1rem;
        padding-left: 2.4rem;
        color: rgba(255, 255, 255, 0.7);
        font-style: italic;
    }
    
    .notification-type-icon {
        font-size: 1.3rem;
        flex-shrink: 0;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 36px;
        height: 36px;
        border-radius: 10px;
        margin-right: 12px;
        transition: all 0.3s ease;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    }
    
    .notification-type-icon:hover {
        transform: scale(1.1) rotate(5deg);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    }
    
    .track_purchase { 
        color: #10b981; 
        background: linear-gradient(135deg, rgba(16, 185, 129, 0.2) 0%, rgba(5, 150, 105, 0.2) 100%);
        border: 2px solid rgba(16, 185, 129, 0.3);
    }
    .ticket_sale { 
        color: #8b5cf6; 
        background: linear-gradient(135deg, rgba(139, 92, 246, 0.2) 0%, rgba(124, 58, 237, 0.2) 100%);
        border: 2px solid rgba(139, 92, 246, 0.3);
    }
    .friend_request { 
        color: #667eea; 
        background: linear-gradient(135deg, rgba(102, 126, 234, 0.2) 0%, rgba(118, 75, 162, 0.2) 100%);
        border: 2px solid rgba(102, 126, 234, 0.3);
    }
    .like { 
        color: #ef4444; 
        background: linear-gradient(135deg, rgba(239, 68, 68, 0.2) 0%, rgba(220, 38, 38, 0.2) 100%);
        border: 2px solid rgba(239, 68, 68, 0.3);
    }
    .comment { 
        color: #22c55e; 
        background: linear-gradient(135deg, rgba(34, 197, 94, 0.2) 0%, rgba(21, 128, 61, 0.2) 100%);
        border: 2px solid rgba(34, 197, 94, 0.3);
    }
    .artist_rating, .track_rating { 
        color: #f59e0b; 
        background: linear-gradient(135deg, rgba(245, 158, 11, 0.2) 0%, rgba(217, 119, 6, 0.2) 100%);
        border: 2px solid rgba(245, 158, 11, 0.3);
    }
    .follow { 
        color: #3b82f6; 
        background: linear-gradient(135deg, rgba(59, 130, 246, 0.2) 0%, rgba(37, 99, 235, 0.2) 100%);
        border: 2px solid rgba(59, 130, 246, 0.3);
    }
    
    .track-link {
        color: #667eea;
        text-decoration: none;
        font-weight: 600;
        transition: color 0.3s ease;
        display: inline;
        white-space: nowrap;
    }
    
    .track-link:hover {
        color: #764ba2;
        text-decoration: underline;
    }
    
    .notification-actions {
        display: flex;
        gap: 1rem;
        flex-wrap: wrap;
    }
    
    .btn-sm {
        padding: 0.5rem 1rem;
        font-size: 1.1rem;
        border-radius: 6px;
    }
    
    .empty-state {
        background: rgba(255, 255, 255, 0.05);
        border: 1px solid rgba(255, 255, 255, 0.1);
        border-radius: 12px;
        padding: 4rem 2rem;
        text-align: center;
        backdrop-filter: blur(10px);
    }
    
    .empty-state-content {
        max-width: 400px;
        margin: 0 auto;
    }
    
    .empty-state i {
        font-size: 4rem;
        color: rgba(255, 255, 255, 0.3);
        margin-bottom: 1.5rem;
    }
    
    .empty-state h3 {
        font-size: 2rem;
        font-weight: 600;
        color: white;
        margin-bottom: 0.8rem;
    }
    
    .empty-state p {
        font-size: 1.4rem;
        color: rgba(255, 255, 255, 0.7);
        margin-bottom: 2rem;
        line-height: 1.5;
    }
    
    .empty-state-actions {
        display: flex;
        gap: 1.5rem;
        justify-content: center;
        flex-wrap: wrap;
    }
    
    .error-card {
        background: rgba(229, 62, 62, 0.1);
        border: 1px solid rgba(229, 62, 62, 0.3);
        border-radius: 12px;
        padding: 2rem;
        text-align: center;
        backdrop-filter: blur(10px);
    }
    
    .error-content {
        max-width: 400px;
        margin: 0 auto;
    }
    
    .error-content i {
        font-size: 3rem;
        color: #e53e3e;
        margin-bottom: 1rem;
    }
    
    .error-content h3 {
        font-size: 2rem;
        font-weight: 600;
        color: #e53e3e;
        margin-bottom: 0.8rem;
    }
    
    .error-content p {
        font-size: 1.4rem;
        color: rgba(255, 255, 255, 0.8);
        margin-bottom: 1.5rem;
    }
    
    /* Responsive Design */
    @media (max-width: 768px) {
        .page-header-content {
            flex-direction: column;
            align-items: flex-start;
            gap: 1.5rem;
        }
        
        .page-title {
            font-size: 2.4rem;
        }
        
        .page-title i {
            font-size: 2rem;
        }
        
        .notification-card {
            flex-direction: column;
            align-items: flex-start;
            gap: 1rem;
        }
        
        .notification-avatar {
            width: 4rem;
            height: 4rem;
            font-size: 1.4rem;
        }
        
        .notification-header {
            flex-direction: column;
            align-items: flex-start;
        }
        
        .notification-actions {
            width: 100%;
            justify-content: flex-start;
        }
        
        .empty-state-actions {
            flex-direction: column;
            align-items: center;
        }
    }
</style>

<script>
    const notificationStrings = <?= json_encode([
        'accepting' => t('notifications.accepting'),
        'accept' => t('notifications.accept'),
        'friendAccepted' => t('notifications.friend_accepted'),
        'failedAccept' => t('notifications.failed_accept'),
        'networkError' => t('notifications.network_error'),
        'declining' => t('notifications.declining'),
        'decline' => t('notifications.decline'),
        'friendDeclined' => t('notifications.friend_declined'),
        'failedDecline' => t('notifications.failed_decline'),
        'stayUpdated' => t('notifications.stay_updated'),
        'marking' => t('notifications.marking'),
        'allMarkedRead' => t('notifications.all_marked_read'),
        'failedMarkRead' => t('notifications.failed_mark_read'),
        'markAllRead' => t('notifications.mark_all_read'),
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    function acceptFriend(senderId, button) {
        const notificationItem = button.closest('.notification-card');
        
        // Show loading state
        button.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${notificationStrings.accepting}`;
        button.disabled = true;
        
        fetch('/api_social.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ 
                action: 'accept_friend', 
                friend_id: senderId 
            })
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                // Remove the notification item with animation
                notificationItem.style.animation = 'slideOut 0.3s ease-out';
                setTimeout(() => {
                    notificationItem.remove();
                    
                    // Update notification count badge in header
                    if (typeof window.updateNotificationsBadge === 'function') {
                        window.updateNotificationsBadge();
                    }
                    
                    // Check if no more notifications
                    const remainingNotifications = document.querySelectorAll('.notification-card');
                    if (remainingNotifications.length === 0) {
                        location.reload(); // Reload to show empty state
                    } else {
                        // Update count on page
                        updateNotificationCount();
                    }
                }, 300);
                
                showNotification(notificationStrings.friendAccepted, 'success');
            } else {
                showNotification(data.message || notificationStrings.failedAccept, 'error');
                button.innerHTML = `<i class="fas fa-check"></i> ${notificationStrings.accept}`;
                button.disabled = false;
            }
        })
        .catch(error => {
            console.error('Error accepting friend:', error);
            showNotification(notificationStrings.networkError, 'error');
            button.innerHTML = `<i class="fas fa-check"></i> ${notificationStrings.accept}`;
            button.disabled = false;
        });
    }
    
    function declineFriend(senderId, button) {
        const notificationItem = button.closest('.notification-card');
        
        // Show loading state
        button.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${notificationStrings.declining}`;
        button.disabled = true;
        
        fetch('/api_social.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ 
                action: 'decline_friend', 
                friend_id: senderId 
            })
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                // Remove the notification item with animation
                notificationItem.style.animation = 'slideOut 0.3s ease-out';
                setTimeout(() => {
                    notificationItem.remove();
                    
                    // Update notification count badge in header
                    if (typeof window.updateNotificationsBadge === 'function') {
                        window.updateNotificationsBadge();
                    }
                    
                    // Check if no more notifications
                    const remainingNotifications = document.querySelectorAll('.notification-card');
                    if (remainingNotifications.length === 0) {
                        location.reload(); // Reload to show empty state
                    } else {
                        // Update count on page
                        updateNotificationCount();
                    }
                }, 300);
                
                showNotification(notificationStrings.friendDeclined, 'info');
            } else {
                showNotification(data.message || notificationStrings.failedDecline, 'error');
                button.innerHTML = `<i class="fas fa-times"></i> ${notificationStrings.decline}`;
                button.disabled = false;
            }
        })
        .catch(error => {
            console.error('Error declining friend:', error);
            showNotification(notificationStrings.networkError, 'error');
            button.innerHTML = `<i class="fas fa-times"></i> ${notificationStrings.decline}`;
            button.disabled = false;
        });
    }
    
    // Function to update notification count on page
    function updateNotificationCount() {
        fetch('/api/get_notification_count.php')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    const count = parseInt(data.unread_count) || 0;
                    const badge = document.querySelector('.notification-count-badge');
                    const subtitle = document.querySelector('.page-subtitle');
                    
                    if (count > 0) {
                        if (badge) {
                            badge.textContent = count;
                        } else {
                            // Create badge if it doesn't exist
                            const title = document.querySelector('.page-title');
                            if (title) {
                                const newBadge = document.createElement('span');
                                newBadge.className = 'notification-count-badge';
                                newBadge.textContent = count;
                                title.appendChild(newBadge);
                            }
                        }
                        
                        // Update subtitle
                        if (subtitle && data.breakdown) {
                            const br = data.breakdown;
                            // Note: This will need server-side translation or a separate API endpoint
                            // For now, keeping English as fallback
                            subtitle.textContent = `You have ${count} notification${count > 1 ? 's' : ''} (${br.friend_requests} friend request${br.friend_requests != 1 ? 's' : ''}, ${br.likes} like${br.likes != 1 ? 's' : ''}, ${br.comments} comment${br.comments != 1 ? 's' : ''})`;
                        }
                    } else {
                        if (badge) {
                            badge.remove();
                        }
                        if (subtitle) {
                            subtitle.textContent = notificationStrings.stayUpdated;
                        }
                    }
                }
            })
            .catch(error => {
                console.error('Error updating notification count:', error);
            });
    }
    
    function viewProfile(userId) {
        window.open(`/artist_profile.php?id=${userId}`, '_blank');
    }
    
    function showNotification(message, type = 'info') {
        // Create notification element
        const notification = document.createElement('div');
        notification.className = `notification-toast ${type}`;
        notification.innerHTML = `
            <i class="fas fa-${type === 'success' ? 'check-circle' : type === 'error' ? 'exclamation-circle' : 'info-circle'}"></i>
            <span>${message}</span>
        `;
        
        // Add to page
        document.body.appendChild(notification);
        
        // Show notification
        setTimeout(() => notification.classList.add('show'), 100);
        
        // Remove after 3 seconds
        setTimeout(() => {
            notification.classList.remove('show');
            setTimeout(() => notification.remove(), 300);
        }, 3000);
    }
    
    // Mark all notifications as read
    function markAllAsRead() {
        const btn = document.getElementById('markAllReadBtn');
        if (btn) {
            btn.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${notificationStrings.marking}`;
            btn.disabled = true;
        }
        
        fetch('/api/mark_notifications_read.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: 'action=mark_all_read'
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                // Update notification count
                updateNotificationCount();
                
                // Update header badge
                if (typeof window.updateNotificationsBadge === 'function') {
                    window.updateNotificationsBadge();
                }
                
                // Hide the button
                if (btn) {
                    btn.style.display = 'none';
                }
                
                // Update page title badge
                const badge = document.querySelector('.notification-count-badge');
                if (badge) {
                    badge.remove();
                }

                // Immediately hide header badge
                const headerBadge = document.getElementById('notificationsBadge');
                if (headerBadge) {
                    headerBadge.style.display = 'none';
                    headerBadge.classList.remove('pulse', 'double-digit', 'triple-digit');
                    headerBadge.textContent = '0';
                }
                
                // Update subtitle
                const subtitle = document.querySelector('.page-subtitle');
                if (subtitle) {
                    subtitle.textContent = notificationStrings.stayUpdated;
                }
                
                showNotification(notificationStrings.allMarkedRead, 'success');
            } else {
                showNotification(data.message || notificationStrings.failedMarkRead, 'error');
                if (btn) {
                    btn.innerHTML = `<i class="fas fa-check-double"></i> ${notificationStrings.markAllRead}`;
                    btn.disabled = false;
                }
            }
        })
        .catch(error => {
            console.error('Error marking notifications as read:', error);
            showNotification(notificationStrings.networkError, 'error');
            if (btn) {
                btn.innerHTML = `<i class="fas fa-check-double"></i> ${notificationStrings.markAllRead}`;
                btn.disabled = false;
            }
        });
    }
    
    // Auto-mark notifications as read when page is viewed (like messages)
    function autoMarkAsRead() {
        // Only mark as read if there are unread notifications
        if (<?= $total_notification_count ?> > 0) {
            fetch('/api/mark_notifications_read.php', {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: 'action=mark_all_read'
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // Update header badge immediately
                    if (typeof window.updateNotificationsBadge === 'function') {
                        window.updateNotificationsBadge();
                    }
                }
            })
            .catch(error => {
                console.error('Error auto-marking notifications:', error);
            });
        }
    }
    
    // Update notification count on page load
    document.addEventListener('DOMContentLoaded', function() {
        updateNotificationCount();
        
        // Auto-mark as read when page loads (like messages does)
        // Delay slightly to ensure page is fully loaded
        setTimeout(autoMarkAsRead, 500);
        
        // Update count every 30 seconds
        setInterval(updateNotificationCount, 30000);
    });
    
    // Add CSS for notification toast and animations
    const style = document.createElement('style');
    style.textContent = `
        .notification-toast {
            position: fixed;
            top: 20px;
            right: 20px;
            background: white;
            padding: 1rem 1.5rem;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            display: flex;
            align-items: center;
            gap: 0.5rem;
            z-index: 1000;
            transform: translateX(100%);
            transition: transform 0.3s ease;
        }
        
        .notification-toast.show {
            transform: translateX(0);
        }
        
        .notification-toast.success {
            border-left: 4px solid #48bb78;
        }
        
        .notification-toast.error {
            border-left: 4px solid #f56565;
        }
        
        .notification-toast.info {
            border-left: 4px solid #667eea;
        }
        
        @keyframes slideOut {
            to {
                opacity: 0;
                transform: translateX(-100%);
            }
        }
    `;
    document.head.appendChild(style);
</script>

<?php
function timeAgo($datetime, $timestamp = null) {
    // Use Unix timestamp if provided (more accurate, avoids timezone issues)
    if ($timestamp !== null && is_numeric($timestamp)) {
        $time = time() - (int)$timestamp;
    } else {
        // Fallback to parsing datetime string
        // Create DateTime object from MySQL datetime string
        $dt = DateTime::createFromFormat('Y-m-d H:i:s', $datetime);
        if ($dt === false) {
            // Try alternative format
            $dt = new DateTime($datetime);
        }
        $time = time() - $dt->getTimestamp();
    }
    
    // Ensure time is not negative (shouldn't happen, but safety check)
    if ($time < 0) {
        $time = 0;
    }
    
    if ($time < 60) {
        return t('notifications.just_now');
    } elseif ($time < 3600) {
        $minutes = floor($time / 60);
        return t($minutes > 1 ? 'notifications.minutes_ago_plural' : 'notifications.minutes_ago', ['count' => $minutes]);
    } elseif ($time < 86400) {
        $hours = floor($time / 3600);
        return t($hours > 1 ? 'notifications.hours_ago_plural' : 'notifications.hours_ago', ['count' => $hours]);
    } elseif ($time < 2592000) {
        $days = floor($time / 86400);
        return t($days > 1 ? 'notifications.days_ago_plural' : 'notifications.days_ago', ['count' => $days]);
    } else {
        // Use the original datetime string for date formatting
        $dt = DateTime::createFromFormat('Y-m-d H:i:s', $datetime);
        if ($dt === false) {
            $dt = new DateTime($datetime);
        }
        return $dt->format('M j, Y');
    }
}

function getNotificationIcon($type) {
    if ($type === 'track_purchase') {
        return 'dollar-sign';
    }
    switch ($type) {
        case 'friend_request':
            return 'user-plus';
        case 'like':
            return 'heart';
        case 'comment':
            return 'comment';
        case 'artist_rating':
        case 'track_rating':
            return 'star';
        case 'follow':
            return 'user-check';
        default:
            return 'bell';
    }
}
?> 

CasperSecurity Mini