
function allTickets() {
    loadTicketCounts();
    $(".crud_section").html("");

    var userObj = JSON.parse(localStorage.getItem('userObj'));

    console.log("User Object:", userObj);

    let ticketsCache = [];
    let filteredTickets = [];
    let usersCache = [];
    let currentPage = 0;
    const pageSize = 12;

    // Filter state
    let currentStatusFilter = 'ALL';
    let currentAssigneeFilter = 'ALL';   // 'ALL', 'ME', 'UNASSIGNED'

    /* PRIORITY ORDER */
    const PRIORITY_ORDER = {
        CRITICAL: 1,
        HIGH: 2,
        MEDIUM: 3,
        LOW: 4
    };

    /* STATUS COLORS */
    const STATUS_STYLES = {
        OPEN: { bg: '#fee2e2', color: '#dc2626', icon: 'fa-circle' },
        ASSIGNED: { bg: '#fff3e0', color: '#ed6c02', icon: 'fa-user-check' },
        IN_PROGRESS: { bg: '#e3f2fd', color: '#1976d2', icon: 'fa-spinner' },
        RESOLVED: { bg: '#e8f5e9', color: '#2e7d32', icon: 'fa-check-circle' },
        CLOSED: { bg: '#f5f5f5', color: '#5b677c', icon: 'fa-archive' },
        REOPENED: { bg: '#fef9c3', color: '#eab308', icon: 'fa-undo-alt' }
    };

    /* ================= INITIAL LOAD ================= */
    loadTicketData();

    function loadTicketData() {
        // Skeleton loader (same as before)
        $(".tab_tickets").html(`
            <div class="alarms-container" style="padding: 24px; background: #ffffff; min-height: 100vh; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
                <!-- Header Skeleton -->
                <div style="background: #ffffff; border-radius: 16px; padding: 24px; margin-bottom: 24px; border: 1px solid #eaeef2;">
                    <div style="height: 32px; width: 200px; background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: loading 1.5s infinite; border-radius: 8px;"></div>
                </div>
                <!-- Stats Skeleton -->
                <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-bottom: 24px;">
                    ${Array(4).fill().map(() => `
                        <div style="height: 100px; background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: loading 1.5s infinite; border-radius: 16px;"></div>
                    `).join('')}
                </div>
                <!-- Grid Skeleton -->
                <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
                    ${Array(6).fill().map(() => `
                        <div style="height: 200px; background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: loading 1.5s infinite; border-radius: 16px;"></div>
                    `).join('')}
                </div>
                <style>
                    @keyframes loading {
                        0% { background-position: 200% 0; }
                        100% { background-position: -200% 0; }
                    }
                </style>
            </div>
        `);

        // Fetch users first (for assignee names), then tickets
        $.ajax({
            url: serverURL + "users/userList?pageNo=0&pageSize=1000",
            type: "GET",
            headers: { Authorization: "Bearer " + userObj.accessToken },
            success: function(users) {
                usersCache = users.map(u => ({
                    userId: u.userId,
                    name: (u.firstName && u.lastName) ? `${u.firstName} ${u.lastName}` : (u.username || u.email || `User ${u.userId}`)
                }));
                fetchTicketsForCurrentUser();
            },
            error: function() {
                usersCache = [];
                fetchTicketsForCurrentUser();
            }
        });

        function fetchTicketsForCurrentUser() {
            // Fetch all tickets assigned to the current user (any status)
            // URL: tickets/assignee/{userId} (remove /status/OPEN to get all)
            $.ajax({
                url: serverURL + "tickets/assignee/" + userObj.id + "?page=0&size=10000000&sort=createdAt,desc",
                type: "GET",
                headers: { Authorization: "Bearer " + userObj.accessToken },
                success: function (response) {
                    const tickets = response.content || response || [];
                    if (tickets.length === 0) {
                        renderEmptyState();
                        return;
                    }

                    ticketsCache = tickets.map(t => ({
                        id: t.id,
                        ticketNumber: t.ticketNumber,
                        title: t.title,
                        description: t.description,
                        priority: t.priority,
                        status: t.status,
                        assignedTo: t.assignee ? {
                            id: t.assignee.userId,
                            name: (t.assignee.firstName && t.assignee.lastName) 
                                ? `${t.assignee.firstName} ${t.assignee.lastName}` 
                                : (t.assignee.username || t.assignee.email || `User ${t.assignee.userId}`)
                        } : null,
                        reporter: t.reporter ? {
                            id: t.reporter.userId,
                            name: (t.reporter.firstName && t.reporter.lastName) 
                                ? `${t.reporter.firstName} ${t.reporter.lastName}` 
                                : (t.reporter.username || t.reporter.email || `User ${t.reporter.userId}`)
                        } : null,
                        sourceNotificationId: t.sourceNotificationId,
                        deviceSerialNumber: t.deviceSerialNumber,
                        geofenceName: t.geofenceName,
                        createdAt: t.createdAt,
                        updatedAt: t.updatedAt,
                        resolvedAt: t.resolvedAt,
                        closedAt: t.closedAt,
                        comments: t.comments ? t.comments.map(c => ({
                            id: c.id,
                            user: c.author ? {
                                id: c.author.userId,
                                name: (c.author.firstName && c.author.lastName) 
                                    ? `${c.author.firstName} ${c.author.lastName}` 
                                    : (c.author.username || c.author.email || `User ${c.author.userId}`)
                            } : { name: 'System' },
                            text: c.content,
                            oldStatus: c.oldStatus,
                            newStatus: c.newStatus,
                            createdAt: c.createdAt
                        })) : [],
                        read: false
                    })).sort((a, b) => {
                        const p1 = PRIORITY_ORDER[a.priority] || 99;
                        const p2 = PRIORITY_ORDER[b.priority] || 99;
                        if (p1 !== p2) return p1 - p2;
                        return new Date(b.createdAt) - new Date(a.createdAt);
                    });

                    applyFilters();
                },
                error: function () {
                    renderErrorState();
                }
            });
        }
    }

    function renderEmptyState() {
        $(".tab_tickets").html(`
            <div class="alarms-container" style="padding: 24px; background: #ffffff; min-height: 100vh;">
                <div style="text-align: center; padding: 60px 20px; background: white; border-radius: 16px; border: 1px solid #eaeef2;">
                    <i class="fas fa-bell-slash" style="font-size: 64px; color: #94a3b8; margin-bottom: 16px;"></i>
                    <h3 style="color: #1a1f36; margin-bottom: 8px;">No Tickets</h3>
                    <p style="color: #5b677c;">All caught up! No tickets assigned to you.</p>
                </div>
            </div>
        `);
    }

    function renderErrorState() {
        $(".tab_tickets").html(`
            <div class="alarms-container" style="padding: 24px; background: #ffffff; min-height: 100vh;">
                <div style="text-align: center; padding: 60px 20px; background: white; border-radius: 16px; border: 1px solid #eaeef2;">
                    <i class="fas fa-exclamation-triangle" style="font-size: 64px; color: #dc2626; margin-bottom: 16px;"></i>
                    <h3 style="color: #1a1f36; margin-bottom: 8px;">Failed to Load Tickets</h3>
                    <p style="color: #5b677c; margin-bottom: 20px;">Please try again</p>
                    <button onclick="allTickets()" style="padding: 10px 24px; background: #000; color: white; border: none; border-radius: 10px; cursor: pointer;">
                        <i class="fas fa-sync-alt"></i> Retry
                    </button>
                </div>
            </div>
        `);
    }

    /* ================= FILTERING ================= */
    function applyFilters() {
        filteredTickets = ticketsCache.filter(ticket => {
            // Status filter
            if (currentStatusFilter !== 'ALL' && ticket.status !== currentStatusFilter) {
                return false;
            }
            // Assignee filter
            if (currentAssigneeFilter === 'ME') {
                if (!ticket.assignedTo || ticket.assignedTo.id !== userObj.id) return false;
            } else if (currentAssigneeFilter === 'UNASSIGNED') {
                if (ticket.assignedTo) return false;
            } // 'ALL' includes all (since all are assigned to current user anyway)
            return true;
        });

        currentPage = 0;
        renderTicketsPage();
    }

    window.onStatusFilterChange = function(value) {
        currentStatusFilter = value;
        applyFilters();
    };

    window.onAssigneeFilterChange = function(value) {
        currentAssigneeFilter = value;
        applyFilters();
    };

    window.clearFilters = function() {
        currentStatusFilter = 'ALL';
        currentAssigneeFilter = 'ALL';
        $('#statusFilter').val('ALL');
        $('#assigneeFilter').val('ALL');
        applyFilters();
    };

    /* ================= RENDER PAGE ================= */
    function renderTicketsPage() {
        const start = currentPage * pageSize;
        const pageItems = filteredTickets.slice(start, start + pageSize);

        const total = filteredTickets.length;

        // Assignee filter options: only "All", "Me", and "Unassigned" (since we only fetch tickets for current user)
        const assigneeOptions = `
            <option value="ALL">All Assignees</option>
            <option value="ME">Assigned to Me</option>
        `;

        let html = `
        <div class="alarms-container" style="padding: 24px; background: #ffffff; min-height: 100vh; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
            
            <!-- Header -->
            <div class="tickets-header" style="background: #ffffff; border-radius: 16px; padding: 24px; margin-bottom: 24px; border: 1px solid #eaeef2; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px;">
                <div style="display: flex; align-items: center; gap: 16px; flex-wrap: wrap;">
                    <h1 style="margin: 0; font-size: 28px; font-weight: 600; color: #1a1f36; display: flex; align-items: center; gap: 12px;">
                        <i class="fas fa-ticket-alt" style="color: #000;"></i>
                        My Tickets
                    </h1>
                    <span style="background: #f0f2f5; color: #1a1f36; padding: 6px 14px; border-radius: 40px; font-size: 14px; font-weight: 500;">
                        ${total} Total
                    </span>
                </div>
                <div style="display: flex; gap: 8px; flex-wrap: wrap;">
                    <button onclick="markAllAsRead()" style="display: flex; align-items: center; gap: 8px; padding: 10px 16px; background: white; color: #1a1f36; border: 1px solid #eaeef2; border-radius: 10px; font-weight: 500; cursor: pointer;">
                        <i class="fas fa-check-double"></i> Mark All Read
                    </button>
                    <button onclick="refreshTickets()" style="width: 40px; height: 40px; border: 1px solid #eaeef2; border-radius: 10px; background: white; cursor: pointer;">
                        <i class="fas fa-sync-alt"></i>
                    </button>
                </div>
            </div>

            <!-- Filter Bar -->
            <div class="filter-bar" style="background: #ffffff; border-radius: 12px; padding: 16px; margin-bottom: 20px; border: 1px solid #eaeef2; display: flex; flex-wrap: wrap; gap: 16px; align-items: center;">
                <div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
                    <label style="font-weight: 500; color: #1a1f36;">Status:</label>
                    <select id="statusFilter" onchange="onStatusFilterChange(this.value)" style="padding: 8px 16px; border: 1px solid #eaeef2; border-radius: 40px; background: white; font-size: 14px;">
                        <option value="ALL">All Statuses</option>
                        <option value="OPEN">Open</option>
                        <option value="ASSIGNED">Assigned</option>
                        <option value="IN_PROGRESS">In Progress</option>
                        <option value="RESOLVED">Resolved</option>
                        <option value="REOPENED">Reopened</option>
                        <option value="CLOSED">Closed</option>
                    </select>
                </div>
                <div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
                    <label style="font-weight: 500; color: #1a1f36;">Assignee:</label>
                    <select id="assigneeFilter" onchange="onAssigneeFilterChange(this.value)" style="padding: 8px 16px; border: 1px solid #eaeef2; border-radius: 40px; background: white; font-size: 14px;">
                        ${assigneeOptions}
                    </select>
                </div>
                <button onclick="clearFilters()" style="padding: 8px 16px; background: #000; color: white; border: none; border-radius: 40px; cursor: pointer;">
                    <i class="fas fa-times"></i> Clear Filters
                </button>
            </div>

            <!-- Tickets Grid -->
            <div class="tickets-grid" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-bottom: 24px;">
        `;

        if (pageItems.length === 0) {
            html += `
                <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: #5b677c;">
                    <i class="fas fa-filter" style="font-size: 32px; margin-bottom: 12px;"></i>
                    <p>No tickets match the selected filters.</p>
                </div>
            `;
        } else {
            pageItems.forEach(item => {
                const priorityColors = {
                    CRITICAL: { bg: '#fee2e2', color: '#dc2626', icon: 'fa-exclamation-circle' },
                    HIGH: { bg: '#ffedd5', color: '#f97316', icon: 'fa-exclamation-triangle' },
                    MEDIUM: { bg: '#fef9c3', color: '#eab308', icon: 'fa-clock' },
                    LOW: { bg: '#e0f2fe', color: '#0284c7', icon: 'fa-info-circle' }
                };
                const priorityStyle = priorityColors[item.priority] || priorityColors.LOW;
                const statusStyle = STATUS_STYLES[item.status] || STATUS_STYLES.OPEN;

                html += `
                    <div class="ticket-card ${item.read ? 'read' : 'unread'}" 
                         data-id="${item.id}"
                         data-read="${item.read}"
                         data-priority="${item.priority}"
                         data-status="${item.status}"
                         data-assignee="${item.assignedTo ? item.assignedTo.id : 'unassigned'}"
                         onclick="openTicketModal(${item.id})"
                         style="cursor: pointer; background: #ffffff; border-radius: 16px; border: 1px solid ${item.read ? '#eaeef2' : '#000'}; overflow: hidden; transition: all 0.2s; box-shadow: 0 2px 8px rgba(0,0,0,0.02);">
                        
                        <!-- Priority Bar -->
                        <div style="height: 4px; background: ${priorityStyle.color};"></div>
                        
                        <!-- Header -->
                        <div style="padding: 16px; border-bottom: 1px solid #eaeef2; display: flex; justify-content: space-between; align-items: center;">
                            <div style="display: flex; align-items: center; gap: 8px;">
                                <i class="fas ${priorityStyle.icon}" style="color: ${priorityStyle.color};"></i>
                                <span style="font-weight: 600; color: #1a1f36; max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${item.title}</span>
                            </div>
                            <span style="font-size: 12px; color: #5b677c;">
                                <i class="far fa-clock"></i> ${formatTimeAgo(item.createdAt)}
                            </span>
                        </div>
                        
                        <!-- Body -->
                        <div style="padding: 16px;">
                            <p style="margin: 0 0 12px 0; color: #1a1f36; line-height: 1.5; font-size: 14px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;">
                                ${item.description || 'No description'}
                            </p>
                            
                            <!-- Status and Assignee Chips -->
                            <div style="display: flex; flex-wrap: wrap; gap: 8px; align-items: center;">
                                <span style="background: ${statusStyle.bg}; color: ${statusStyle.color}; padding: 4px 10px; border-radius: 40px; font-size: 11px; font-weight: 600;">
                                    <i class="fas ${statusStyle.icon}"></i> ${item.status}
                                </span>
                                <span style="background: #f0f2f5; color: #5b677c; padding: 4px 10px; border-radius: 40px; font-size: 11px; display: flex; align-items: center; gap: 4px;">
                                    <i class="fas fa-user"></i> ${item.assignedTo ? item.assignedTo.name : 'Unassigned'}
                                </span>
                                <span style="background: ${priorityStyle.bg}; color: ${priorityStyle.color}; padding: 4px 10px; border-radius: 40px; font-size: 11px;">
                                    ${item.priority}
                                </span>
                            </div>
                        </div>
                        
                        <!-- Footer with quick actions -->
                        <div class="ticket-footer" style="padding: 12px 16px; background: #f8fafc; border-top: 1px solid #eaeef2; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;">
                            <div style="display: flex; gap: 8px; flex-wrap: wrap;">
                                ${!item.read ? `
                                    <button onclick="event.stopPropagation(); markAsRead(${item.id}, this)" 
                                            style="padding: 4px 10px; background: white; border: 1px solid #eaeef2; border-radius: 6px; font-size: 11px; color: #1a1f36; cursor: pointer; display: flex; align-items: center; gap: 4px;">
                                        <i class="fas fa-check"></i> Read
                                    </button>
                                ` : ''}
                                
                                ${item.assignedTo && item.assignedTo.id === userObj.id ? '' : `
                                    <button onclick="event.stopPropagation(); assignToMe(${item.id}, this)" 
                                            style="padding: 4px 10px; background: #000; border: none; border-radius: 6px; font-size: 11px; color: white; cursor: pointer; display: flex; align-items: center; gap: 4px;">
                                        <i class="fas fa-user-plus"></i> Assign me
                                    </button>
                                `}
                                
                                ${item.status !== 'RESOLVED' && item.status !== 'CLOSED' ? `
                                    <button onclick="event.stopPropagation(); quickResolve(${item.id}, this)" 
                                            style="padding: 4px 10px; background: #10b981; border: none; border-radius: 6px; font-size: 11px; color: white; cursor: pointer; display: flex; align-items: center; gap: 4px;">
                                        <i class="fas fa-check-circle"></i> Resolve
                                    </button>
                                ` : ''}

                                <button onclick="event.stopPropagation(); openReAssignModal(${item.id}, this)" 
                                        style="padding: 4px 10px; background: #3b82f6; border: none; border-radius: 6px; font-size: 11px; color: white; cursor: pointer; display: flex; align-items: center; gap: 4px;">
                                    <i class="fas fa-user-plus"></i> Re-Assign
                                </button>
                            </div>
                            
                            ${item.deviceSerialNumber ? `
                                <button onclick="event.stopPropagation(); viewDeviceOnMap('${item.deviceSerialNumber}')" 
                                        style="padding: 4px 10px; background: #e3f2fd; border: none; border-radius: 6px; font-size: 11px; color: #1976d2; cursor: pointer; display: flex; align-items: center; gap: 4px;">
                                    <i class="fas fa-map-marker-alt"></i> Map
                                </button>
                            ` : ''}
                        </div>
                    </div>
                `;
            });
        }

        html += `
            </div>
            
            <!-- Pagination -->
            <div class="pagination" style="background: #ffffff; border-radius: 12px; padding: 16px; border: 1px solid #eaeef2; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px;">
                <div style="color: #5b677c; font-size: 14px;">
                    Showing ${start + 1} to ${Math.min(start + pageSize, filteredTickets.length)} of ${filteredTickets.length} tickets
                </div>
                
                <div style="display: flex; gap: 8px; flex-wrap: wrap;">
                    <button ${currentPage === 0 ? 'disabled' : ''} 
                            onclick="changePage(${currentPage - 1})"
                            style="padding: 8px 16px; border: 1px solid #eaeef2; border-radius: 8px; background: white; color: #1a1f36; cursor: ${currentPage === 0 ? 'not-allowed' : 'pointer'}; opacity: ${currentPage === 0 ? 0.5 : 1};">
                        <i class="fas fa-chevron-left"></i> Previous
                    </button>
                    
                    <span style="padding: 8px 16px; background: #f8fafc; border-radius: 8px; color: #1a1f36; font-weight: 500;">
                        Page ${currentPage + 1} of ${Math.ceil(filteredTickets.length / pageSize)}
                    </span>
                    
                    <button ${currentPage >= Math.ceil(filteredTickets.length / pageSize) - 1 ? 'disabled' : ''} 
                            onclick="changePage(${currentPage + 1})"
                            style="padding: 8px 16px; border: 1px solid #eaeef2; border-radius: 8px; background: white; color: #1a1f36; cursor: ${currentPage >= Math.ceil(filteredTickets.length / pageSize) - 1 ? 'not-allowed' : 'pointer'}; opacity: ${currentPage >= Math.ceil(filteredTickets.length / pageSize) - 1 ? 0.5 : 1};">
                        Next <i class="fas fa-chevron-right"></i>
                    </button>
                </div>
            </div>
            
            <style>
                .ticket-card:hover {
                    transform: translateY(-2px);
                    box-shadow: 0 8px 16px rgba(0,0,0,0.05) !important;
                }
                .ticket-card.unread {
                    border-left-width: 3px;
                }
                /* Responsive adjustments */
                @media (max-width: 1024px) {
                    .alarms-container { padding: 16px !important; }
                    .tickets-grid { grid-template-columns: repeat(2, 1fr) !important; }
                }
                @media (max-width: 768px) {
                    .tickets-grid { grid-template-columns: 1fr !important; }
                    .tickets-header { flex-direction: column; align-items: stretch; }
                    .tickets-header > div:first-child { justify-content: space-between; }
                    .filter-bar { flex-direction: column; align-items: stretch; }
                    .filter-bar > div { width: 100%; }
                    .filter-bar select { width: 100%; }
                    .ticket-footer { flex-direction: column; align-items: stretch; }
                    .ticket-footer > div { justify-content: center; }
                    .pagination { flex-direction: column; align-items: stretch; }
                    .pagination > div { text-align: center; }
                }
                @media (max-width: 480px) {
                    .ticket-footer > div { flex-wrap: wrap; justify-content: center; }
                }
            </style>
        </div>
        `;

        $(".tab_tickets").html(html);
    }

    /* ================= PAGINATION ================= */
    window.changePage = function(page) {
        currentPage = page;
        renderTicketsPage();
    };

    /* ================= RE-ASSIGN MODAL ================= */
    window.openReAssignModal = function(id, btn) {
        event.stopPropagation();
        if (usersCache.length === 0) {
            Swal.fire({ title: 'Loading users...', allowOutsideClick: false, didOpen: () => Swal.showLoading() });
            $.ajax({
                url: serverURL + "users/userList?pageNo=0&pageSize=10",
                type: "GET",
                headers: { Authorization: "Bearer " + userObj.accessToken },
                success: function (users) {
                    usersCache = users.map(u => ({
                        userId: u.userId,
                        name: (u.firstName && u.lastName) ? `${u.firstName} ${u.lastName}` : (u.username || u.email || `User ${u.userId}`)
                    }));
                    Swal.close();
                    showReAssignModal(id, btn);
                },
                error: function () {
                    Swal.fire({ title: 'Error', text: 'Could not load users', icon: 'error' });
                }
            });
        } else {
            showReAssignModal(id, btn);
        }
    };

    function showReAssignModal(id, btn) {
        let options = '<option value="">Select a user</option>';
        usersCache.forEach(u => {
            options += `<option value="${u.userId}">${u.name}</option>`;
        });

        Swal.fire({
            title: 'Re‑Assign Ticket',
            html: `
               <form class="ui form" id="login" autocomplete="off" style="padding:18px">
                <div style="text-align: left;">
                    <label style="font-weight: 600; font-size: 14px;">Select User</label>
                    <select id="swal-user-select" style="width: 100%; padding: 10px; border: 1px solid #eaeef2; border-radius: 8px; margin: 5px 0 15px 0;">
                        ${options}
                    </select>
                    <label style="font-weight: 600; font-size: 14px;">Comment</label>
                    <textarea id="swal-assign-comment" placeholder="Add a comment (optional)" style="width: 100%; padding: 10px; border: 1px solid #eaeef2; border-radius: 8px; resize: vertical; min-height: 80px;"></textarea>
                </div>
                </form>
            `,
            showCancelButton: true,
            confirmButtonText: 'Re‑Assign',
            confirmButtonColor: '#3b82f6',
            preConfirm: () => {
                const userId = $('#swal-user-select').val();
                const comment = $('#swal-assign-comment').val();
                if (!userId) {
                    Swal.showValidationMessage('Please select a user');
                    return false;
                }
                return { userId, comment };
            }
        }).then((result) => {
            if (result.isConfirmed) {
                const { userId, comment } = result.value;
                $.ajax({
                    url: serverURL + `tickets/${id}/assign`,
                    type: "POST",
                    headers: {
                        Authorization: "Bearer " + userObj.accessToken,
                        "Content-Type": "application/json"
                    },
                    data: JSON.stringify({ 
                        assigneeId: parseInt(userId), 
                        comment: comment || ''
                    }),
                    success: function (updatedTicket) {
                        const ticket = ticketsCache.find(t => t.id == id);
                        if (ticket) {
                            ticket.assignedTo = usersCache.find(u => u.userId == userId) || null;
                        }
                        refreshTickets();
                        Swal.fire({
                            title: 'Re‑Assigned',
                            text: 'Ticket reassigned successfully',
                            icon: 'success',
                            timer: 1500,
                            showConfirmButton: false
                        });
                    },
                    error: function(xhr) {
                        Swal.fire({ 
                            title: 'Error', 
                            text: 'Re‑assignment failed: ' + (xhr.responseJSON?.message || ''), 
                            icon: 'error' 
                        });
                    }
                });
            }
        });
    }

    /* ================= TICKET DETAIL MODAL ================= */
    window.openTicketModal = function(id) {
        const ticket = ticketsCache.find(t => t.id == id);
        if (!ticket) return;

        const statusStyle = STATUS_STYLES[ticket.status] || STATUS_STYLES.OPEN;

        let commentsHtml = '';
        if (ticket.comments && ticket.comments.length) {
            commentsHtml = ticket.comments.map(c => `
                <div style="margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid #eaeef2;">
                    <div style="display: flex; justify-content: space-between; align-items: center;">
                        <strong>${c.user.name}</strong>
                        <span style="color: #5b677c; font-size: 12px;">${new Date(c.createdAt).toLocaleString()}</span>
                    </div>
                    <p style="margin: 8px 0 0 0; color: #1a1f36;">${c.text}</p>
                    ${c.oldStatus && c.newStatus ? `<p style="margin: 4px 0 0 0; font-size: 11px; color: #5b677c;">Status changed: ${c.oldStatus} → ${c.newStatus}</p>` : ''}
                </div>
            `).join('');
        } else {
            commentsHtml = '<p style="color: #94a3b8;">No comments yet.</p>';
        }

        const modalHtml = `
        <div id="ticketModal" style="display: block; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 10002; backdrop-filter: blur(4px);">
            <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 700px; max-height: 85vh; background: white; border-radius: 24px; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,0.3); display: flex; flex-direction: column;">
                
                <!-- Header -->
                <div style="padding: 20px 24px; background: #ffffff; border-bottom: 1px solid #eaeef2; display: flex; justify-content: space-between; align-items: center;">
                    <div>
                        <h3 style="margin: 0 0 4px 0; font-size: 20px; color: #1a1f36;">${ticket.title}</h3>
                        <span style="background: ${statusStyle.bg}; color: ${statusStyle.color}; padding: 4px 12px; border-radius: 40px; font-size: 12px;">
                            <i class="fas ${statusStyle.icon}"></i> ${ticket.status}
                        </span>
                    </div>
                    <button onclick="closeTicketModal()" style="width: 36px; height: 36px; border: 1px solid #eaeef2; border-radius: 50%; background: white; cursor: pointer;">
                        <i class="fas fa-times"></i>
                    </button>
                </div>
                
                <!-- Body (scrollable) -->
                <div style="padding: 24px; overflow-y: auto; flex: 1;">
                    <!-- Priority & timestamps -->
                    <div class="modal-info-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 16px; margin-bottom: 24px;">
                        <div>
                            <span style="font-size: 12px; color: #5b677c;">Priority</span>
                            <div><span style="font-weight: 500;">${ticket.priority}</span></div>
                        </div>
                        <div>
                            <span style="font-size: 12px; color: #5b677c;">Created</span>
                            <div><span style="font-weight: 500;">${new Date(ticket.createdAt).toLocaleString()}</span></div>
                        </div>
                        <div>
                            <span style="font-size: 12px; color: #5b677c;">Updated</span>
                            <div><span style="font-weight: 500;">${new Date(ticket.updatedAt).toLocaleString()}</span></div>
                        </div>
                        ${ticket.deviceSerialNumber ? `
                        <div>
                            <span style="font-size: 12px; color: #5b677c;">Device</span>
                            <div><span style="font-weight: 500;">${ticket.deviceSerialNumber}</span></div>
                        </div>` : ''}
                    </div>
                    
                    <!-- Description -->
                    <div style="margin-bottom: 24px;">
                        <span style="font-size: 12px; color: #5b677c; display: block; margin-bottom: 4px;">Description</span>
                        <p style="margin: 0; background: #f8fafc; padding: 16px; border-radius: 12px; white-space: pre-wrap;">${ticket.description}</p>
                    </div>
                    
                    <!-- Geofence info if present -->
                    ${ticket.geofenceName ? `
                    <div style="margin-bottom: 24px;">
                        <span style="font-size: 12px; color: #5b677c;">Geofence</span>
                        <div style="font-weight: 500;">${ticket.geofenceName}</div>
                    </div>` : ''}
                    
                    <!-- Assignee & Status controls -->
                    <div class="modal-controls-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 24px;">
                        <div>
                            <label style="font-size: 12px; color: #5b677c; display: block; margin-bottom: 6px;">Assignee</label>
                            <select id="modalAssigneeSelect" class="ticket-select" style="width: 100%; padding: 10px; border: 1px solid #eaeef2; border-radius: 10px;">
                                <option value="">Unassigned</option>
                                ${usersCache.map(u => `<option value="${u.userId}" ${ticket.assignedTo && ticket.assignedTo.id == u.userId ? 'selected' : ''}>${u.name}</option>`).join('')}
                            </select>
                        </div>
                        <div>
                            <label style="font-size: 12px; color: #5b677c; display: block; margin-bottom: 6px;">Status</label>
                            <select id="modalStatusSelect" class="ticket-select" style="width: 100%; padding: 10px; border: 1px solid #eaeef2; border-radius: 10px;">
                                ${Object.keys(STATUS_STYLES).map(s => `<option value="${s}" ${ticket.status == s ? 'selected' : ''}>${s}</option>`).join('')}
                            </select>
                        </div>
                    </div>

                    <!-- Comments history -->
                    <div>
                        <h4 style="font-size: 16px; margin: 0 0 16px 0;">Comments History</h4>
                        <div id="modalCommentsList" style="max-height: 200px; overflow-y: auto; border: 1px solid #eaeef2; padding: 16px; border-radius: 12px; margin-bottom: 16px;">
                            ${commentsHtml}
                        </div>

                        <!-- Comment field for actions -->
                        <div style="margin-bottom: 24px;">
                            <label style="font-size: 12px; color: #5b677c; display: block; margin-bottom: 6px;">Comment (required for changes)</label>
                            <textarea id="modalActionComment" placeholder="Add a comment for this change..." style="width: 100%; padding: 10px; border: 1px solid #eaeef2; border-radius: 10px; resize: vertical; min-height: 60px;"></textarea>
                            <div id="modalCommentError" style="color: #dc2626; font-size: 12px; margin-top: 4px; display: none;">Comment is required for this change.</div>
                        </div>
                    
                        <div style="display: flex; gap: 8px;">
                            <button onclick="addCommentToTicket(${ticket.id})" style="background: #000; color: white; border: none; border-radius: 10px; padding: 10px 20px; cursor: pointer;">
                                <i class="fas fa-paper-plane"></i> Add Comment
                            </button>
                        </div>
                    </div>
                </div>
                
                <!-- Footer -->
                <div style="padding: 16px 24px; border-top: 1px solid #eaeef2; display: flex; justify-content: flex-end; gap: 12px;">
                    <button onclick="closeTicketModal()" style="padding: 10px 20px; background: white; border: 1px solid #eaeef2; border-radius: 10px; cursor: pointer;">Close</button>
                </div>
            </div>
        </div>
        `;

        $('body').append(modalHtml);

        $('#modalActionComment').on('input', function() {
            $('#modalCommentError').hide();
        });

        const originalAssignee = ticket.assignedTo ? ticket.assignedTo.id : '';
        const originalStatus = ticket.status;

        $('#modalAssigneeSelect').on('change', function() {
            const newVal = $(this).val();
            const comment = $('#modalActionComment').val().trim();
            if (!comment) {
                $('#modalCommentError').show();
                $(this).val(originalAssignee);
                return;
            }
            $('#modalCommentError').hide();
            updateTicketAssignee(ticket.id, newVal, comment);
        });

        $('#modalStatusSelect').on('change', function() {
            const newVal = $(this).val();
            const comment = $('#modalActionComment').val().trim();
            if (!comment) {
                $('#modalCommentError').show();
                $(this).val(originalStatus);
                return;
            }
            $('#modalCommentError').hide();
            updateTicketStatus(ticket.id, newVal, comment);
        });

        // Responsive modal adjustments
        $('<style>')
            .prop('type', 'text/css')
            .html(`
                @media (max-width: 600px) {
                    #ticketModal > div { width: 95%; max-height: 90vh; }
                    .modal-info-grid { grid-template-columns: 1fr 1fr !important; }
                    .modal-controls-grid { grid-template-columns: 1fr !important; }
                }
            `)
            .appendTo('head');
    };

    window.closeTicketModal = function() {
        $('#ticketModal').remove();
    };

    function updateTicketAssignee(ticketId, userId, comment) {
        $.ajax({
            url: serverURL + `tickets/${ticketId}/assign`,
            type: 'POST',
            headers: { Authorization: "Bearer " + userObj.accessToken },
            contentType: 'application/json',
            data: JSON.stringify({ assigneeId: userId || null, comment: comment }),
            success: function(updatedTicket) {
                const ticket = ticketsCache.find(t => t.id == ticketId);
                if (ticket) {
                    ticket.assignedTo = userId ? usersCache.find(u => u.userId == userId) : null;
                }
                closeTicketModal();
                refreshTickets();
                Swal.fire({ title: 'Success', text: 'Assignee updated', icon: 'success', timer: 1500, showConfirmButton: false });
            },
            error: function(xhr) {
                Swal.fire({ title: 'Error', text: 'Failed to update assignee: ' + (xhr.responseJSON?.message || ''), icon: 'error' });
            }
        });
    }

    function updateTicketStatus(ticketId, newStatus, comment) {
        $.ajax({
            url: serverURL + `tickets/${ticketId}/status`,
            type: 'PUT',
            headers: { Authorization: "Bearer " + userObj.accessToken },
            contentType: 'application/json',
            data: JSON.stringify({ newStatus: newStatus, comment: comment }),
            success: function(updatedTicket) {
                const ticket = ticketsCache.find(t => t.id == ticketId);
                if (ticket) {
                    ticket.status = newStatus;
                }
                closeTicketModal();
                refreshTickets();
                Swal.fire({ title: 'Success', text: 'Status updated', icon: 'success', timer: 1500, showConfirmButton: false });
            },
            error: function(xhr) {
                Swal.fire({ title: 'Error', text: 'Failed to update status: ' + (xhr.responseJSON?.message || ''), icon: 'error' });
            }
        });
    }

    window.addCommentToTicket = function(ticketId) {
        const comment = $('#modalActionComment').val().trim();
        if (!comment) {
            $('#modalCommentError').show();
            return;
        }

        const ticket = ticketsCache.find(t => t.id == ticketId);
        if (!ticket) return;

        $.ajax({
            url: serverURL + `tickets/${ticketId}/status`,
            type: 'PUT',
            headers: { Authorization: "Bearer " + userObj.accessToken },
            contentType: 'application/json',
            data: JSON.stringify({ newStatus: ticket.status, comment: comment }),
            success: function(updatedTicket) {
                if (updatedTicket.comments) {
                    ticket.comments = updatedTicket.comments.map(c => ({
                        id: c.id,
                        user: c.author ? {
                            id: c.author.userId,
                            name: (c.author.firstName && c.author.lastName) 
                                ? `${c.author.firstName} ${c.author.lastName}` 
                                : (c.author.username || c.author.email || `User ${c.author.userId}`)
                        } : { name: 'System' },
                        text: c.content,
                        oldStatus: c.oldStatus,
                        newStatus: c.newStatus,
                        createdAt: c.createdAt
                    }));
                }
                closeTicketModal();
                Swal.fire({ title: 'Comment Added', icon: 'success', timer: 1500, showConfirmButton: false });
            },
            error: function(xhr) {
                Swal.fire({ title: 'Error', text: 'Failed to add comment: ' + (xhr.responseJSON?.message || ''), icon: 'error' });
            }
        });
    };

    /* ================= QUICK ACTIONS ================= */
    window.assignToMe = function(id, btn) {
        event.stopPropagation();
        Swal.fire({
            title: 'Assign to Me',
            input: 'textarea',
            inputLabel: 'Comment',
            inputPlaceholder: 'Enter a comment...',
            inputAttributes: { required: true },
            showCancelButton: true,
            confirmButtonText: 'Assign',
            confirmButtonColor: '#000',
            preConfirm: (comment) => {
                if (!comment) {
                    Swal.showValidationMessage('Comment is required');
                    return false;
                }
                return comment;
            }
        }).then((result) => {
            if (result.isConfirmed) {
                const userId = userObj.id;
                $.ajax({
                    url: serverURL + `tickets/${id}/assign`,
                    type: 'POST',
                    headers: { Authorization: "Bearer " + userObj.accessToken },
                    contentType: 'application/json',
                    data: JSON.stringify({ assigneeId: userId, comment: result.value }),
                    success: function(updatedTicket) {
                        refreshTickets();
                        Swal.fire({ title: 'Assigned', text: 'Ticket assigned to you', icon: 'success', timer: 1500, showConfirmButton: false });
                    },
                    error: function(xhr) {
                        Swal.fire({ title: 'Error', text: 'Failed to assign: ' + (xhr.responseJSON?.message || ''), icon: 'error' });
                    }
                });
            }
        });
    };

    window.quickResolve = function(id, btn) {
        event.stopPropagation();
        Swal.fire({
            title: 'Resolve Ticket',
            input: 'textarea',
            inputLabel: 'Resolution Comment',
            inputPlaceholder: 'Explain how this was resolved...',
            inputAttributes: { required: true },
            showCancelButton: true,
            confirmButtonText: 'Resolve',
            confirmButtonColor: '#10b981',
            preConfirm: (comment) => {
                if (!comment) {
                    Swal.showValidationMessage('Comment is required');
                    return false;
                }
                return comment;
            }
        }).then((result) => {
            if (result.isConfirmed) {
                $.ajax({
                    url: serverURL + `tickets/${id}/status`,
                    type: 'PUT',
                    headers: { Authorization: "Bearer " + userObj.accessToken },
                    contentType: 'application/json',
                    data: JSON.stringify({ newStatus: 'RESOLVED', comment: result.value }),
                    success: function(updatedTicket) {
                        refreshTickets();
                        Swal.fire({ title: 'Resolved', text: 'Ticket marked as resolved', icon: 'success', timer: 1500, showConfirmButton: false });
                    },
                    error: function(xhr) {
                        Swal.fire({ title: 'Error', text: 'Failed to resolve: ' + (xhr.responseJSON?.message || ''), icon: 'error' });
                    }
                });
            }
        });
    };

    /* ================= MAP FUNCTIONS (unchanged) ================= */
    window.viewDeviceOnMap = function(deviceSerialNumber) {
        if (typeof focusDevice === "function") {
            $('.tab-item[onclick*="position"]').click();
            setTimeout(() => {
                focusDevice(deviceSerialNumber);
            }, 500);
        } else {
            openmap(deviceSerialNumber);
        }
    };

    let historyMap;
    let historyPolyline;

    window.openmap = function(deviceSerialNumber) {
        $.ajax({
            url: serverURL + "telemetry/device/" + deviceSerialNumber + "?page=0&size=10",
            type: "GET",
            dataType: "json",
            headers: { Authorization: "Bearer " + userObj.accessToken },
            success: function (response) {
                if (!response.content || response.content.length < 2) {
                    Swal.fire({
                        title: 'Insufficient Data',
                        text: 'Not enough data points to draw path',
                        icon: 'warning',
                        confirmButtonColor: '#000'
                    });
                    return;
                }
                drawHistoryMap(response.content.reverse(), deviceSerialNumber);
            },
            error: function () {
                Swal.fire({
                    title: 'Error',
                    text: 'Failed to load device history',
                    icon: 'error',
                    confirmButtonColor: '#000'
                });
            }
        });
    };

    window.drawHistoryMap = function(data, deviceSn) {
        if ($('#historyMapModal').length === 0) {
            $('body').append(`
                <div id="historyMapModal" style="display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 10000; backdrop-filter: blur(4px);">
                    <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 1200px; height: 80%; background: white; border-radius: 24px; overflow: hidden; box-shadow: 0 20px 60px rgba(0,0,0,0.3);">
                        <div style="padding: 16px 20px; background: #ffffff; border-bottom: 1px solid #eaeef2; display: flex; justify-content: space-between; align-items: center;">
                            <h3 style="margin: 0; font-size: 18px; color: #1a1f36;">
                                <i class="fas fa-history" style="margin-right: 8px; color: #000;"></i>
                                Device History - ${deviceSn}
                            </h3>
                            <button onclick="closeHistoryMap()" style="width: 36px; height: 36px; border: 1px solid #eaeef2; border-radius: 50%; background: white; cursor: pointer;">
                                <i class="fas fa-times"></i>
                            </button>
                        </div>
                        <div id="historyMap" style="height: calc(100% - 70px); width: 100%;"></div>
                    </div>
                </div>
            `);
        }

        $("#historyMapModal").fadeIn(150);

        const pathCoords = data
            .filter(d => d.latitude && d.longitude)
            .map(d => ({ lat: d.latitude, lng: d.longitude }));

        const start = pathCoords[0];
        const end = pathCoords[pathCoords.length - 1];

        historyMap = new google.maps.Map(
            document.getElementById("historyMap"),
            {
                zoom: 14,
                center: end,
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                gestureHandling: "greedy",
                zoomControl: true,
                streetViewControl: true,
                mapTypeControl: true,
                fullscreenControl: true,
                styles: [
                    {
                        featureType: "poi",
                        elementType: "labels",
                        stylers: [{ visibility: "off" }]
                    }
                ]
            }
        );

        historyPolyline = new google.maps.Polyline({
            path: pathCoords,
            geodesic: true,
            strokeColor: "#1976d2",
            strokeOpacity: 0.9,
            strokeWeight: 4,
            icons: [{
                icon: { path: google.maps.SymbolPath.FORWARD_OPEN_ARROW },
                offset: '100%',
                repeat: '100px'
            }]
        });
        historyPolyline.setMap(historyMap);

        new google.maps.Marker({
            position: start,
            map: historyMap,
            icon: { url: "https://maps.google.com/mapfiles/ms/icons/green-dot.png", scaledSize: new google.maps.Size(40, 40) },
            title: "Start"
        });

        new google.maps.Marker({
            position: end,
            map: historyMap,
            icon: { url: "https://maps.google.com/mapfiles/ms/icons/red-dot.png", scaledSize: new google.maps.Size(40, 40) },
            title: "Current Position"
        });

        const bounds = new google.maps.LatLngBounds();
        pathCoords.forEach(p => bounds.extend(p));
        historyMap.fitBounds(bounds);
    };

    window.closeHistoryMap = function() {
        $("#historyMapModal").fadeOut(150);
        if (historyPolyline) {
            historyPolyline.setMap(null);
        }
    };

    /* ================= READ ACTIONS ================= */
    window.markAsRead = function(id, btn) {
        event.stopPropagation();
        const $card = $(btn).closest('.ticket-card');
        $card.attr('data-read', 'true');
        $card.css('border-color', '#eaeef2');
        $(btn).fadeOut(300, function() { $(this).remove(); });
        const ticket = ticketsCache.find(t => t.id == id);
        if (ticket) ticket.read = true;
    };

    window.markAllAsRead = function() {
        const unreadIds = ticketsCache.filter(t => !t.read).map(t => t.id);
        if (unreadIds.length === 0) {
            Swal.fire({ title: 'Info', text: 'No unread tickets', icon: 'info' });
            return;
        }
        ticketsCache.forEach(t => { t.read = true; });
        refreshTickets();
        Swal.fire({ title: 'Success', text: 'All marked as read (locally)', icon: 'success', timer: 2000, showConfirmButton: false });
    };

    window.refreshTickets = function() {
        loadTicketData();
    };

    function formatTimeAgo(dateString) {
        const date = new Date(dateString);
        const now = new Date();
        const seconds = Math.floor((now - date) / 1000);
        if (seconds < 60) return 'just now';
        if (seconds < 3600) return Math.floor(seconds / 60) + ' minutes ago';
        if (seconds < 86400) return Math.floor(seconds / 3600) + ' hours ago';
        if (seconds < 604800) return Math.floor(seconds / 86400) + ' days ago';
        return date.toLocaleDateString();
    }
}