const root = document.getElementById('app');

if (!root) {
    throw new Error('Frontend root element #app was not found.');
}

const categoryPresets = ['Hardware', 'Software', 'Network', 'Access', 'Billing', 'Security', 'General'];
const priorityOptions = ['Low', 'Medium', 'High', 'Urgent'];
const statusOptions = ['open', 'in-progress', 'waiting-customer', 'waiting-internal', 'resolved', 'closed'];
const agentFilters = [
    { value: 'my-tickets', label: 'My Tickets' },
    { value: 'unassigned', label: 'Unassigned' },
    { value: 'all-tickets', label: 'All Visible' },
    { value: 'urgent', label: 'Urgent' },
    { value: 'overdue', label: 'Overdue' },
    { value: 'waiting', label: 'Waiting' },
    { value: 'resolved', label: 'Resolved / Closed Today' },
];

const state = {
    booting: true,
    loading: false,
    loadingLabel: '',
    notice: '',
    error: '',
    authMode: 'login',
    user: null,
    view: 'overview',
    tickets: [],
    ticketPagination: null,
    agentFilter: 'my-tickets',
    selectedTicketId: null,
    selectedTicket: null,
    chatMessages: [],
    ticketMessages: [],
    generalUnread: 0,
    userDirectory: [],
    adminUsers: [],
    stats: null,
    adminStats: null,
    adminSla: [],
    adminUploads: [],
    clientKeys: [],
    uploadedAttachments: [],
};

function escapeHtml(value) {
    return String(value ?? '')
        .replaceAll('&', '&amp;')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;')
        .replaceAll("'", '&#39;');
}

function formatDate(value) {
    if (!value) {
        return 'N/A';
    }

    const date = new Date(value);

    if (Number.isNaN(date.getTime())) {
        return String(value);
    }

    return new Intl.DateTimeFormat(undefined, {
        dateStyle: 'medium',
        timeStyle: 'short',
    }).format(date);
}

function statusTone(status) {
    const map = {
        open: 'badge badge-open',
        'in-progress': 'badge badge-progress',
        'waiting-customer': 'badge badge-waiting',
        'waiting-internal': 'badge badge-internal',
        resolved: 'badge badge-resolved',
        closed: 'badge badge-closed',
    };

    return map[status] || 'badge';
}

function priorityTone(priority) {
    const map = {
        Low: 'badge badge-low',
        Medium: 'badge badge-medium',
        High: 'badge badge-high',
        Urgent: 'badge badge-urgent',
    };

    return map[priority] || 'badge';
}

function availableStatusOptions(currentStatus) {
    if (currentStatus === 'closed') {
        return ['closed'];
    }

    return statusOptions;
}

function currentOrganizationName() {
    return state.user?.organization || state.user?.department || '';
}

function adminAccessLabel() {
    return state.user?.is_super_admin ? 'Super Admin' : 'Organization Admin';
}

function renderOrganizationSections() {
    const organizations = state.adminStats?.organizations || [];

    if (!organizations.length) {
        return `
            <section class="panel">
                <div class="section-heading">
                    <h2>Organizations</h2>
                    <span class="muted">No assigned organization</span>
                </div>
                <p class="muted">Assign this admin to an organization to unlock organization-scoped tickets, users, and metrics.</p>
            </section>
        `;
    }

    return `
        <section class="panel">
            <div class="section-heading">
                <h2>Organizations</h2>
                <span class="muted">${organizations.length} visible</span>
            </div>
            <div class="admin-list">
                ${organizations
                    .map(
                        (organization) => `
                    <article class="admin-item">
                        <div>
                            <strong>${escapeHtml(organization.name)}</strong>
                            <p>${escapeHtml(organization.usersCount)} users · ${escapeHtml(organization.ticketsCount)} tickets</p>
                        </div>
                        <div class="status-column">
                            <span class="badge badge-open">${escapeHtml(organization.openTicketsCount)} open</span>
                            <span class="badge badge-waiting">${escapeHtml(organization.pendingTicketsCount || 0)} pending</span>
                            <span class="badge badge-resolved">${escapeHtml(organization.resolvedTicketsCount)} resolved</span>
                        </div>
                    </article>
                    <article class="admin-item compact-item">
                        <div>
                            <strong>Recent tickets</strong>
                            <p>${
                                organization.tickets?.length
                                    ? organization.tickets
                                          .map((ticket) => `${ticket.id} - ${ticket.title}`)
                                          .join(' | ')
                                    : 'No tickets yet'
                            }</p>
                        </div>
                    </article>
                    <article class="admin-item compact-item">
                        <div>
                            <strong>Users</strong>
                            <p>${
                                organization.users?.length
                                    ? organization.users
                                          .map((user) => `${user.name} (${user.role})`)
                                          .join(' | ')
                                    : 'No users yet'
                            }</p>
                        </div>
                    </article>
                `
                    )
                    .join('')}
            </div>
        </section>
    `;
}

function roleViews(role) {
    const base = [
        { key: 'overview', label: 'Overview' },
        { key: 'tickets', label: 'Tickets' },
        { key: 'create', label: 'New Ticket' },
        { key: 'chat', label: 'Team Chat' },
    ];

    if (role === 'admin') {
        return [...base, { key: 'admin', label: 'Admin' }];
    }

    if (role === 'agent') {
        return [...base, { key: 'queue', label: 'Agent Queue' }];
    }

    return base;
}

function setLoading(loading, label = '') {
    state.loading = loading;
    state.loadingLabel = loading ? label : '';
    render();
}

function flashNotice(message) {
    state.notice = message;
    state.error = '';
    render();
}

function flashError(message) {
    state.error = message;
    render();
}

async function api(method, url, data, config = {}) {
    try {
        const isFormData = typeof FormData !== 'undefined' && data instanceof FormData;
        const headers = new Headers(config.headers || {});

        if (!isFormData && data !== undefined && !headers.has('Content-Type')) {
            headers.set('Content-Type', 'application/json');
        }

        const response = await fetch(`/api${url}`, {
            method: method.toUpperCase(),
            headers,
            credentials: 'same-origin',
            body: data === undefined ? undefined : isFormData ? data : JSON.stringify(data),
        });

        if (response.status === 204) {
            return null;
        }

        const contentType = response.headers.get('content-type') || '';
        const payload = contentType.includes('application/json') ? await response.json() : await response.text();

        if (!response.ok) {
            const message =
                payload?.message ||
                payload?.error ||
                (typeof payload === 'string' ? payload : '') ||
                'Request failed.';
            throw new Error(message);
        }

        return payload;
    } catch (error) {
        throw new Error(error?.message || 'Request failed.');
    }
}

function defaultViewForRole(role) {
    if (role === 'admin' || role === 'agent') {
        return 'overview';
    }

    return 'tickets';
}

async function bootstrapApp() {
    render();

    try {
        const user = await api('get', '/auth/me');
        state.user = user;
        state.view = defaultViewForRole(user.role);
        await loadAllData();
    } catch {
        state.user = null;
    } finally {
        state.booting = false;
        render();
    }
}

async function loadAllData() {
    const tasks = [loadTickets(), loadGeneralChat()];

    if (state.user?.role === 'agent') {
        tasks.push(loadAgentStats(), loadDirectory());
    }

    if (state.user?.role === 'admin') {
        tasks.push(loadAdminStats(), loadAdminData(), loadDirectory());
    }

    if (state.user?.role === 'user') {
        tasks.push(loadDirectory());
    }

    await Promise.all(tasks);
}

async function loadDirectory() {
    try {
        state.userDirectory = await api('get', '/users');
    } catch {
        state.userDirectory = [];
    }
}

async function loadTickets() {
    if (!state.user) {
        return;
    }

    if (state.user.role === 'agent' || state.user.role === 'admin') {
        state.tickets = await api('get', `/agent/tickets?filter=${encodeURIComponent(state.agentFilter)}`);
        state.ticketPagination = null;
    } else {
        const data = await api('get', '/tickets?per_page=50');
        state.tickets = data.data || [];
        state.ticketPagination = data.meta || null;
    }

    if (!state.selectedTicketId && state.tickets.length > 0) {
        state.selectedTicketId = state.tickets[0].id;
        await loadTicketDetail(state.selectedTicketId);
    } else if (state.selectedTicketId) {
        const stillVisible = state.tickets.some((ticket) => ticket.id === state.selectedTicketId);

        if (stillVisible) {
            await loadTicketDetail(state.selectedTicketId);
        } else {
            state.selectedTicketId = state.tickets[0]?.id ?? null;
            state.selectedTicket = null;
        }
    }
}

async function loadTicketDetail(ticketId) {
    if (!ticketId) {
        state.selectedTicket = null;
        state.ticketMessages = [];
        render();
        return;
    }

    const ticket = await api('get', `/tickets/${ticketId}`);
    state.selectedTicketId = ticketId;
    state.selectedTicket = ticket;

    try {
        state.ticketMessages = (await api('get', `/messages/ticket/${ticketId}`)).data || [];
    } catch {
        state.ticketMessages = [];
    }

    render();
}

async function loadGeneralChat() {
    try {
        const response = await api('get', '/messages');
        state.chatMessages = response.data || [];
    } catch {
        state.chatMessages = [];
    }

    try {
        const unread = await api('get', '/messages/unread/count');
        state.generalUnread = unread.count ?? 0;
    } catch {
        state.generalUnread = 0;
    }
}

async function loadAgentStats() {
    try {
        state.stats = await api('get', '/agent/stats');
    } catch {
        state.stats = null;
    }
}

async function loadAdminStats() {
    try {
        state.adminStats = await api('get', '/admin/stats');
    } catch {
        state.adminStats = null;
    }
}

async function loadAdminData() {
    const [users, sla, uploads, clientKeys] = await Promise.all([
        api('get', '/admin/users'),
        api('get', '/admin/sla-monitoring'),
        api('get', '/admin/uploads'),
        api('get', '/admin/client-keys'),
    ]);

    state.adminUsers = users;
    state.adminSla = sla;
    state.adminUploads = uploads;
    state.clientKeys = clientKeys;
}

async function authenticate(form) {
    const formData = new FormData(form);
    const isRegister = form.dataset.form === 'register';
    const payload = {
        email: formData.get('email'),
        password: formData.get('password'),
    };

    if (isRegister) {
        payload.name = formData.get('name');
        payload.role = formData.get('role') || 'user';
        payload.organization = formData.get('organization') || null;
        payload.category = formData.get('category') || null;
    }

    const endpoint = isRegister ? '/auth/register' : '/auth/login';

    setLoading(true, isRegister ? 'Creating account...' : 'Signing in...');

    try {
        await api('post', endpoint, payload);
        state.notice = isRegister ? 'Account created successfully.' : 'Welcome back.';
        state.error = '';
        state.user = await api('get', '/auth/me');
        state.view = defaultViewForRole(state.user.role);
        await loadAllData();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function logout() {
    setLoading(true, 'Signing out...');

    try {
        await api('post', '/auth/logout');
    } catch {
        // Keep logout resilient even if the token is already gone.
    } finally {
        Object.assign(state, {
            loading: false,
            loadingLabel: '',
            notice: 'Signed out.',
            error: '',
            user: null,
            view: 'overview',
            tickets: [],
            selectedTicketId: null,
            selectedTicket: null,
            chatMessages: [],
            ticketMessages: [],
            stats: null,
            adminStats: null,
            adminUsers: [],
            clientKeys: [],
            adminUploads: [],
            adminSla: [],
            uploadedAttachments: [],
        });
        render();
    }
}

async function createTicket(form) {
    const formData = new FormData(form);
    const payload = {
        title: formData.get('title'),
        description: formData.get('description'),
        category: formData.get('category'),
        priority: formData.get('priority') || null,
        requesterId: state.user.id,
        requesterName: state.user.name,
        organization: formData.get('organization') || currentOrganizationName() || null,
        attachmentIds: state.uploadedAttachments.map((item) => item.id),
    };

    setLoading(true, 'Creating ticket...');

    try {
        const ticket = await api('post', '/tickets', payload);
        state.uploadedAttachments = [];
        flashNotice(`Ticket ${ticket.id} created.`);
        form.reset();
        state.view = 'tickets';
        await loadTickets();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function uploadAttachment(input) {
    const file = input.files?.[0];

    if (!file) {
        return;
    }

    const formData = new FormData();
    formData.append('file', file);

    setLoading(true, 'Uploading attachment...');

    try {
        const attachment = await api('post', '/uploads', formData, {
            headers: { 'Content-Type': 'multipart/form-data' },
        });
        state.uploadedAttachments = [...state.uploadedAttachments, attachment];
        flashNotice(`Uploaded ${attachment.filename}.`);
    } catch (error) {
        flashError(error.message);
    } finally {
        input.value = '';
        setLoading(false);
    }
}

async function addComment(form) {
    if (state.selectedTicket?.status === 'closed') {
        flashError('Closed tickets are read-only.');
        return;
    }

    const formData = new FormData(form);
    const payload = {
        message: formData.get('message'),
        isInternal: formData.get('isInternal') === 'on',
    };

    setLoading(true, 'Posting note...');

    try {
        await api('post', `/tickets/${state.selectedTicketId}/comments`, payload);
        form.reset();
        flashNotice('Comment added.');
        await loadTicketDetail(state.selectedTicketId);
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function sendMessage(form) {
    const formData = new FormData(form);
    const roomType = form.dataset.roomType;
    const roomId = form.dataset.roomId || null;

    if (roomType === 'ticket' && state.selectedTicket?.status === 'closed') {
        flashError('Closed tickets are read-only.');
        return;
    }

    setLoading(true, 'Sending message...');

    try {
        await api('post', '/messages', {
            message: formData.get('message'),
            room_type: roomType,
            room_id: roomId,
        });
        form.reset();

        if (roomType === 'general') {
            await loadGeneralChat();
        } else if (roomType === 'ticket' && roomId) {
            await loadTicketDetail(roomId);
        }
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function takeTicket() {
    if (!state.selectedTicketId) {
        return;
    }

    setLoading(true, 'Assigning ticket...');

    try {
        await api('patch', `/agent/tickets/${state.selectedTicketId}/assign`, { assignToMe: true });
        flashNotice('Ticket assigned to you.');
        await loadTickets();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function escalateTicket() {
    if (!state.selectedTicketId) {
        return;
    }

    setLoading(true, 'Escalating ticket...');

    try {
        await api('patch', `/agent/tickets/${state.selectedTicketId}/escalate`);
        flashNotice('Ticket escalated.');
        await loadTickets();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function updateTicketStatus(form) {
    const formData = new FormData(form);
    const status = formData.get('status');

    if (!status || !state.selectedTicketId) {
        return;
    }

    if (state.selectedTicket?.status === 'closed') {
        flashError('Closed tickets cannot be reopened.');
        return;
    }

    setLoading(true, 'Updating status...');

    try {
        const endpoint =
            state.user.role === 'admin'
                ? `/admin/tickets/${state.selectedTicketId}/status`
                : `/agent/tickets/${state.selectedTicketId}/status`;

        await api('patch', endpoint, { status });
        flashNotice('Status updated.');
        await loadTickets();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function assignAgents(form) {
    const formData = new FormData(form);
    const agentIds = formData
        .getAll('agentIds')
        .map((id) => Number(id))
        .filter(Boolean);

    if (agentIds.length === 0 || !state.selectedTicketId) {
        flashError('Select at least one agent.');
        return;
    }

    setLoading(true, 'Assigning agents...');

    try {
        await api('patch', `/admin/tickets/${state.selectedTicketId}/assign`, { agentIds });
        flashNotice('Agents updated.');
        await loadTickets();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function updateUserRole(form) {
    const formData = new FormData(form);
    const userId = form.dataset.userId;

    setLoading(true, 'Updating user...');

    try {
        await api('patch', `/admin/users/${userId}/role`, {
            role: formData.get('role'),
            organization: formData.get('organization') || null,
            category: formData.get('category') || null,
        });
        flashNotice('User updated.');
        await loadAdminData();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function createClientKey(form) {
    const formData = new FormData(form);

    setLoading(true, 'Creating client key...');

    try {
        const created = await api('post', '/admin/client-keys', {
            client_name: formData.get('client_name'),
            allowed_origins: formData.get('allowed_origins') || null,
        });

        flashNotice(`Client key created. Secret: ${created.api_secret}`);
        form.reset();
        await loadAdminData();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function deleteClientKey(id) {
    setLoading(true, 'Deleting client key...');

    try {
        await api('delete', `/admin/client-keys/${id}`);
        flashNotice('Client key deleted.');
        await loadAdminData();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function deleteUpload(id) {
    const confirmed = window.confirm('Delete this upload? This action cannot be undone.');

    if (!confirmed) {
        return;
    }

    setLoading(true, 'Deleting upload...');

    try {
        await api('delete', `/admin/uploads/${id}`);
        flashNotice('Upload deleted.');
        await loadAdminData();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

async function deleteTicket() {
    if (!state.selectedTicketId) {
        return;
    }

    setLoading(true, 'Deleting ticket...');

    try {
        await api('delete', `/tickets/${state.selectedTicketId}`);
        flashNotice('Ticket deleted.');
        state.selectedTicketId = null;
        state.selectedTicket = null;
        await loadTickets();
    } catch (error) {
        flashError(error.message);
    } finally {
        setLoading(false);
    }
}

function metricCard(label, value) {
    return `
        <article class="metric-card">
            <span>${escapeHtml(label)}</span>
            <strong>${escapeHtml(value)}</strong>
        </article>
    `;
}

function renderMetricCards() {
    if (state.user?.role === 'agent' && state.stats) {
        return `
            <div class="metric-grid">
                ${metricCard('Open Work', state.stats.myOpenTickets)}
                ${metricCard('Urgent', state.stats.urgentTickets)}
                ${metricCard('Overdue', state.stats.overdueTickets)}
                ${metricCard('Resolved Today', state.stats.resolvedToday)}
                ${metricCard('Avg Response', `${state.stats.averageResponseTime}h`)}
                ${metricCard('SLA Compliance', `${state.stats.slaCompliance}%`)}
            </div>
        `;
    }

    if (state.user?.role === 'admin' && state.adminStats) {
        return `
            <div class="metric-grid">
                ${metricCard('Access', state.adminStats.isSuperAdmin ? 'Super Admin' : 'Org Admin')}
                ${metricCard('Organization', state.adminStats.organization || 'Unassigned')}
                ${metricCard('Users', state.adminStats.totalUsers)}
                ${metricCard('Tickets', state.adminStats.totalTickets)}
                ${metricCard('Comments', state.adminStats.totalComments)}
                ${metricCard('Uploads', state.adminUploads.length)}
            </div>
        `;
    }

    const total = state.tickets.length;
    const open = state.tickets.filter((ticket) =>
        ['open', 'in-progress', 'waiting-customer', 'waiting-internal'].includes(ticket.status)
    ).length;
    const resolved = state.tickets.filter((ticket) => ticket.status === 'resolved' || ticket.status === 'closed').length;

    return `
        <div class="metric-grid">
            ${metricCard('My Tickets', total)}
            ${metricCard('Active', open)}
            ${metricCard('Resolved', resolved)}
            ${metricCard('Unread Chat', state.generalUnread)}
        </div>
    `;
}

function renderOverview() {
    const recentTickets = state.tickets.slice(0, 5);
    const spotlight = state.selectedTicket || recentTickets[0];

    return `
        <section class="panel hero-panel">
            <div>
                <p class="eyebrow">Support cockpit</p>
                <h1>${escapeHtml(state.user.name)}</h1>
                <p class="lede">
                    ${escapeHtml(state.user.role)} workspace tuned to the Laravel backend routes already in this project.
                </p>
            </div>
            <div class="hero-meta">
                <span class="hero-chip">${escapeHtml(state.user.email)}</span>
                <span class="hero-chip">${escapeHtml(state.user.is_super_admin ? 'All Organizations' : currentOrganizationName() || 'No organization')}</span>
                <span class="hero-chip">${escapeHtml(adminAccessLabel())}</span>
                <span class="hero-chip">${escapeHtml(state.user.category || 'No specialty')}</span>
            </div>
        </section>
        ${renderMetricCards()}
        ${state.user.role === 'admin' ? renderOrganizationSections() : ''}
        <section class="panel split-panel">
            <div>
                <div class="section-heading">
                    <h2>Recent tickets</h2>
                    <button class="ghost-button" data-nav="tickets">Open workspace</button>
                </div>
                <div class="ticket-stack">
                    ${
                        recentTickets.length
                            ? recentTickets
                                  .map(
                                      (ticket) => `
                                <button class="ticket-card" data-ticket-id="${escapeHtml(ticket.id)}" data-nav="tickets">
                                    <div class="ticket-card-top">
                                        <strong>${escapeHtml(ticket.title)}</strong>
                                        <span class="${statusTone(ticket.status)}">${escapeHtml(ticket.status)}</span>
                                    </div>
                                    <p>${escapeHtml(ticket.description || '').slice(0, 120)}</p>
                                    <div class="ticket-card-bottom">
                                        <span class="${priorityTone(ticket.priority)}">${escapeHtml(ticket.priority || 'Auto')}</span>
                                        <span>${escapeHtml(ticket.id)}</span>
                                    </div>
                                </button>
                            `
                                  )
                                  .join('')
                            : '<p class="muted">No tickets yet. Create the first issue from the New Ticket tab.</p>'
                    }
                </div>
            </div>
            <div>
                <div class="section-heading">
                    <h2>Spotlight</h2>
                    <span class="muted">${spotlight ? 'Live details' : 'Nothing selected yet'}</span>
                </div>
                ${
                    spotlight
                        ? `
                    <div class="spotlight-card">
                        <div class="ticket-card-top">
                            <strong>${escapeHtml(spotlight.title)}</strong>
                            <span class="${priorityTone(spotlight.priority)}">${escapeHtml(spotlight.priority)}</span>
                        </div>
                        <p>${escapeHtml(spotlight.description)}</p>
                        <dl class="detail-grid">
                            <div><dt>ID</dt><dd>${escapeHtml(spotlight.id)}</dd></div>
                            <div><dt>Status</dt><dd>${escapeHtml(spotlight.status)}</dd></div>
                            <div><dt>Requester</dt><dd>${escapeHtml(spotlight.requesterName || spotlight.requester_name || 'Unknown')}</dd></div>
                            <div><dt>Updated</dt><dd>${escapeHtml(formatDate(spotlight.updatedAt || spotlight.updated_at))}</dd></div>
                        </dl>
                    </div>
                `
                        : '<p class="muted">Once tickets load, the selected one will show here.</p>'
                }
            </div>
        </section>
    `;
}

function renderTicketList() {
    return `
        <div class="ticket-list">
            ${state.tickets
                .map((ticket) => {
                    const requester = ticket.requesterName || ticket.requester_name || ticket.requester || 'Unknown';
                    const active = state.selectedTicketId === ticket.id ? 'ticket-row active' : 'ticket-row';

                    return `
                        <button class="${active}" data-ticket-id="${escapeHtml(ticket.id)}">
                            <div class="ticket-card-top">
                                <strong>${escapeHtml(ticket.title)}</strong>
                                <span class="${statusTone(ticket.status)}">${escapeHtml(ticket.status)}</span>
                            </div>
                            <p>${escapeHtml(ticket.description || '').slice(0, 110)}</p>
                            <div class="ticket-card-bottom">
                                <span>${escapeHtml(ticket.id)}</span>
                                <span>${escapeHtml(requester)}</span>
                                <span class="${priorityTone(ticket.priority)}">${escapeHtml(ticket.priority || 'Auto')}</span>
                            </div>
                        </button>
                    `;
                })
                .join('')}
        </div>
    `;
}

function renderTicketDetail() {
    const ticket = state.selectedTicket;

    if (!ticket) {
        return `
            <div class="empty-state">
                <h3>Select a ticket</h3>
                <p>Pick an item from the queue to see comments, attachments, and status actions.</p>
            </div>
        `;
    }

    const availableAgents = (state.adminUsers.length ? state.adminUsers : state.userDirectory).filter(
        (user) => user.role === 'agent' || user.role === 'admin'
    );
    const statusChoices = availableStatusOptions(ticket.status);
    const isClosedTicket = ticket.status === 'closed';

    return `
        <div class="detail-header">
            <div>
                <p class="eyebrow">${escapeHtml(ticket.id)}</p>
                <h2>${escapeHtml(ticket.title)}</h2>
            </div>
            <div class="detail-actions">
                <span class="${statusTone(ticket.status)}">${escapeHtml(ticket.status)}</span>
                <span class="${priorityTone(ticket.priority)}">${escapeHtml(ticket.priority)}</span>
            </div>
        </div>
        <p class="detail-description">${escapeHtml(ticket.description)}</p>
        <dl class="detail-grid">
            <div><dt>Requester</dt><dd>${escapeHtml(ticket.requesterName || ticket.requester_name || ticket.requester || 'Unknown')}</dd></div>
            <div><dt>Organization</dt><dd>${escapeHtml(ticket.department || 'N/A')}</dd></div>
            <div><dt>Assigned</dt><dd>${escapeHtml(ticket.assignedTo?.name || ticket.assigned_to?.name || 'Unassigned')}</dd></div>
            <div><dt>First Response SLA</dt><dd>${escapeHtml(formatDate(ticket.firstResponseSLA || ticket.first_response_sla))}</dd></div>
            <div><dt>Resolution SLA</dt><dd>${escapeHtml(formatDate(ticket.resolutionSLA || ticket.resolution_sla))}</dd></div>
            <div><dt>Updated</dt><dd>${escapeHtml(formatDate(ticket.updatedAt || ticket.updated_at))}</dd></div>
        </dl>
        ${
            state.user.role !== 'user'
                ? `
            <section class="action-band">
                <form data-form="ticket-status" class="inline-form">
                    <label>
                        <span>Status</span>
                        <select name="status">
                            ${statusChoices
                                .map(
                                    (status) =>
                                        `<option value="${status}" ${ticket.status === status ? 'selected' : ''}>${escapeHtml(status)}</option>`
                                )
                                .join('')}
                        </select>
                    </label>
                    <button class="primary-button" type="submit" ${isClosedTicket ? 'disabled' : ''}>Update Status</button>
                </form>
                ${isClosedTicket ? '<p class="muted">Closed tickets are final and cannot be reopened.</p>' : ''}
                ${
                    state.user.role === 'agent' && !isClosedTicket
                        ? `
                    <button class="secondary-button" data-action="assign-self">Assign to Me</button>
                    <button class="ghost-button" data-action="escalate-ticket">Escalate</button>
                `
                        : ''
                }
                ${
                    state.user.role === 'admin'
                        ? `
                    <form data-form="assign-agents" class="assign-form">
                        <label>
                            <span>Assign agents</span>
                            <select name="agentIds" multiple size="4">
                                ${availableAgents
                                    .map((user) => {
                                        const selected = (ticket.agents || []).some((agent) => String(agent.id) === String(user.id));
                                        const label = `${user.name} (${user.role}${user.category ? `, ${user.category}` : ''})`;

                                        return `<option value="${escapeHtml(user.id)}" ${selected ? 'selected' : ''}>${escapeHtml(label)}</option>`;
                                    })
                                    .join('')}
                            </select>
                        </label>
                        <button class="primary-button" type="submit">Save Assignment</button>
                    </form>
                `
                        : ''
                }
            </section>
        `
                : ''
        }
        <section class="panel nested-panel">
            <div class="section-heading">
                <h3>Attachments</h3>
                <span class="muted">${ticket.attachments?.length || 0} file(s)</span>
            </div>
            ${
                ticket.attachments?.length
                    ? `
                <div class="attachment-list">
                    ${ticket.attachments
                        .map(
                            (attachment) => `
                        <a class="attachment-item" href="/${escapeHtml(attachment.path)}" target="_blank" rel="noreferrer">
                            <strong>${escapeHtml(attachment.filename)}</strong>
                            <span>${escapeHtml(attachment.mimeType || attachment.mime_type || 'file')}</span>
                        </a>
                    `
                        )
                        .join('')}
                </div>
            `
                    : '<p class="muted">No files attached to this ticket.</p>'
            }
        </section>
    `;
}

function renderTicketConversation(ticket) {
    const isClosedTicket = ticket.status === 'closed';

    return `
        <section class="panel nested-panel">
            <div class="section-heading">
                <h3>Conversation</h3>
                <span class="muted">${ticket.comments?.length || 0} notes</span>
            </div>
            <div class="comment-list">
                ${
                    ticket.comments?.length
                        ? ticket.comments
                              .map(
                                  (comment) => `
                            <article class="comment-item">
                                <div class="ticket-card-top">
                                    <strong>${escapeHtml(comment.user?.name || comment.author?.name || 'Unknown')}</strong>
                                    <span class="${comment.isInternal || comment.is_internal ? 'badge badge-internal' : 'badge badge-open'}">
                                        ${escapeHtml(comment.isInternal || comment.is_internal ? 'Internal' : 'Public')}
                                    </span>
                                </div>
                                <p>${escapeHtml(comment.message || comment.content)}</p>
                                <small>${escapeHtml(formatDate(comment.createdAt || comment.created_at))}</small>
                            </article>
                        `
                              )
                              .join('')
                        : '<p class="muted">No comments yet.</p>'
                }
            </div>
            ${
                isClosedTicket
                    ? '<p class="muted">This ticket is closed. Existing notes remain visible, but new comments are disabled.</p>'
                    : `
                <form data-form="add-comment" class="stack-form">
                    <label>
                        <span>Add note</span>
                        <textarea name="message" rows="4" placeholder="Write the next update..." required></textarea>
                    </label>
                    ${
                        state.user.role !== 'user'
                            ? `
                        <label class="checkbox-row">
                            <input type="checkbox" name="isInternal" />
                            <span>Internal note</span>
                        </label>
                    `
                            : ''
                    }
                    <button class="primary-button" type="submit">Post Comment</button>
                </form>
            `
            }
        </section>
        <section class="panel nested-panel">
            <div class="section-heading">
                <h3>Ticket room</h3>
                <span class="muted">${state.ticketMessages.length} message(s)</span>
            </div>
            <div class="message-list compact">
                ${
                    state.ticketMessages.length
                        ? state.ticketMessages
                              .map(
                                  (message) => `
                            <article class="message-item">
                                <strong>${escapeHtml(message.user?.name || 'Unknown')}</strong>
                                <p>${escapeHtml(message.message)}</p>
                                <small>${escapeHtml(formatDate(message.created_at))}</small>
                            </article>
                        `
                              )
                              .join('')
                        : '<p class="muted">No ticket-room messages yet.</p>'
                }
            </div>
            ${
                isClosedTicket
                    ? '<p class="muted">This ticket room is read-only because the ticket is closed.</p>'
                    : `
                <form data-form="send-message" data-room-type="ticket" data-room-id="${escapeHtml(ticket.id)}" class="inline-form">
                    <input type="text" name="message" placeholder="Send a quick room update..." required />
                    <button class="primary-button" type="submit">Send</button>
                </form>
            `
            }
        </section>
        ${
            state.user.role !== 'agent'
                ? `
            <div class="danger-zone">
                <button class="danger-button" data-action="delete-ticket">Delete Ticket</button>
            </div>
        `
                : ''
        }
    `;
}

function renderTicketsView() {
    return `
        <section class="panel workspace-panel">
            <div class="workspace-toolbar">
                <div>
                    <p class="eyebrow">Ticket workspace</p>
                    <h2>${state.user.role === 'user' ? 'My requests' : 'Operational queue'}</h2>
                </div>
                ${
                    state.user.role !== 'user'
                        ? `
                    <label class="filter-box">
                        <span>View</span>
                        <select data-agent-filter>
                            ${agentFilters
                                .map(
                                    (option) =>
                                        `<option value="${option.value}" ${state.agentFilter === option.value ? 'selected' : ''}>${escapeHtml(
                                            option.label
                                        )}</option>`
                                )
                                .join('')}
                        </select>
                    </label>
                `
                        : ''
                }
            </div>
            <div class="workspace-grid">
                ${renderTicketList()}
                <div class="ticket-detail">
                    ${renderTicketDetail()}
                    ${state.selectedTicket ? renderTicketConversation(state.selectedTicket) : ''}
                </div>
            </div>
        </section>
    `;
}

function renderCreateView() {
    return `
        <section class="panel create-panel">
            <div class="section-heading">
                <div>
                    <p class="eyebrow">New request</p>
                    <h2>Create a ticket</h2>
                </div>
                <span class="muted">Uploads map directly to the backend attachment flow.</span>
            </div>
            <form data-form="create-ticket" class="form-grid">
                <label>
                    <span>Title</span>
                    <input type="text" name="title" placeholder="Short summary" required />
                </label>
                <label>
                    <span>Category</span>
                    <input list="category-options" name="category" placeholder="Hardware, Billing..." required />
                </label>
                <label class="full-width">
                    <span>Description</span>
                    <textarea name="description" rows="6" placeholder="Describe the issue clearly..." required></textarea>
                </label>
                <label>
                    <span>Priority</span>
                    <select name="priority">
                        <option value="">Auto-detect</option>
                        ${priorityOptions.map((priority) => `<option value="${priority}">${escapeHtml(priority)}</option>`).join('')}
                    </select>
                </label>
                <label>
                    <span>Organization</span>
                    <input
                        type="text"
                        name="organization"
                        value="${escapeHtml(currentOrganizationName() || '')}"
                        placeholder="Finance, HR..."
                        ${state.user.role === 'user' ? 'readonly' : ''}
                        required
                    />
                </label>
                <div class="full-width upload-box">
                    <label>
                        <span>Attach file</span>
                        <input type="file" data-upload-input />
                    </label>
                    ${
                        state.uploadedAttachments.length
                            ? `
                        <div class="attachment-list">
                            ${state.uploadedAttachments
                                .map(
                                    (attachment) => `
                                <div class="attachment-item">
                                    <strong>${escapeHtml(attachment.filename)}</strong>
                                    <span>${escapeHtml(attachment.mimeType || attachment.mime_type || 'file')}</span>
                                </div>
                            `
                                )
                                .join('')}
                        </div>
                    `
                            : '<p class="muted">Upload optional screenshots, PDFs, or supporting files before submitting.</p>'
                    }
                </div>
                <button class="primary-button full-width" type="submit">Create Ticket</button>
            </form>
            <datalist id="category-options">
                ${categoryPresets.map((category) => `<option value="${escapeHtml(category)}"></option>`).join('')}
            </datalist>
        </section>
    `;
}

function renderChatView() {
    return `
        <section class="panel chat-panel">
            <div class="section-heading">
                <div>
                    <p class="eyebrow">General room</p>
                    <h2>Team chat</h2>
                </div>
                <button class="ghost-button" data-action="refresh-chat">Refresh</button>
            </div>
            <div class="message-list">
                ${
                    state.chatMessages.length
                        ? state.chatMessages
                              .map(
                                  (message) => `
                            <article class="message-item">
                                <div class="ticket-card-top">
                                    <strong>${escapeHtml(message.user?.name || 'Unknown')}</strong>
                                    <span class="badge">${escapeHtml(message.user?.role || 'member')}</span>
                                </div>
                                <p>${escapeHtml(message.message)}</p>
                                <small>${escapeHtml(formatDate(message.created_at))}</small>
                            </article>
                        `
                              )
                              .join('')
                        : '<p class="muted">No messages yet. Start the room.</p>'
                }
            </div>
            <form data-form="send-message" data-room-type="general" class="inline-form">
                <input type="text" name="message" placeholder="Share an update with the team..." required />
                <button class="primary-button" type="submit">Send</button>
            </form>
        </section>
    `;
}

function renderAdminView() {
    return `
        <section class="admin-grid">
            <article class="panel">
                <div class="section-heading">
                    <h2>Organization Access</h2>
                    <span class="muted">${escapeHtml(adminAccessLabel())}</span>
                </div>
                <p class="muted">
                    ${
                        state.user.is_super_admin
                            ? 'This Super Admin can view and manage all organizations, all users, and all tickets.'
                            : `This admin can only view and manage tickets, users, and uploads that belong to ${escapeHtml(
                                  currentOrganizationName() || 'the assigned organization once one is set'
                              )}.`
                    }
                </p>
            </article>
            ${renderOrganizationSections()}
            <article class="panel">
                <div class="section-heading">
                    <h2>User management</h2>
                    <span class="muted">${state.adminUsers.length} users</span>
                </div>
                <div class="admin-list">
                    ${state.adminUsers
                        .map(
                            (user) => `
                        <form data-form="update-user-role" data-user-id="${escapeHtml(user.id)}" class="admin-item">
                            <div>
                                <strong>${escapeHtml(user.name)}</strong>
                                <p>${escapeHtml(user.email)}</p>
                                <small class="muted">${escapeHtml(user.isSuperAdmin ? 'Super Admin' : user.role)}</small>
                            </div>
                            <label>
                                <span>Role</span>
                                <select name="role">
                                    ${['user', 'agent', 'admin']
                                        .map(
                                            (role) => `
                                        <option value="${role}" ${user.role === role ? 'selected' : ''}>${escapeHtml(role)}</option>
                                    `
                                        )
                                        .join('')}
                                </select>
                            </label>
                            <label>
                                <span>Organization</span>
                                <input type="text" name="organization" value="${escapeHtml(user.organization || user.department || '')}" />
                            </label>
                            <label>
                                <span>Category</span>
                                <input type="text" name="category" value="${escapeHtml(user.category || '')}" />
                            </label>
                            <button class="secondary-button" type="submit">Save</button>
                        </form>
                    `
                        )
                        .join('')}
                </div>
            </article>
            <article class="panel">
                <div class="section-heading">
                    <h2>Client API keys</h2>
                    <span class="muted">${state.clientKeys.length} integrations</span>
                </div>
                <form data-form="create-client-key" class="stack-form">
                    <label>
                        <span>Client name</span>
                        <input type="text" name="client_name" placeholder="Acme Inc." required />
                    </label>
                    <label>
                        <span>Allowed origins</span>
                        <textarea name="allowed_origins" rows="3" placeholder="https://app.example.com,https://portal.example.com"></textarea>
                    </label>
                    <button class="primary-button" type="submit">Create Key</button>
                </form>
                <div class="admin-list">
                    ${state.clientKeys
                        .map(
                            (key) => `
                        <article class="admin-item">
                            <div>
                                <strong>${escapeHtml(key.client_name)}</strong>
                                <p>${escapeHtml(key.api_key)}</p>
                            </div>
                            <div class="status-column">
                                <span class="${key.is_active ? 'badge badge-resolved' : 'badge badge-closed'}">${
                                    key.is_active ? 'Active' : 'Inactive'
                                }</span>
                                <small>${escapeHtml(key.allowed_origins || 'Any origin')}</small>
                            </div>
                            <button class="danger-button" type="button" data-delete-client-key="${escapeHtml(key.id)}">Delete</button>
                        </article>
                    `
                        )
                        .join('')}
                </div>
            </article>
            <article class="panel">
                <div class="section-heading">
                    <h2>SLA monitoring</h2>
                    <span class="muted">${state.adminSla.length} tracked tickets</span>
                </div>
                <div class="admin-list">
                    ${state.adminSla
                        .slice(0, 12)
                        .map(
                            (ticket) => `
                        <article class="admin-item compact-item">
                            <div>
                                <strong>${escapeHtml(ticket.title)}</strong>
                                <p>${escapeHtml(ticket.id)}</p>
                            </div>
                            <div class="status-column">
                                <span class="${ticket.firstResponseOverdue ? 'badge badge-urgent' : 'badge badge-resolved'}">
                                    ${ticket.firstResponseOverdue ? 'First response overdue' : 'First response ok'}
                                </span>
                                <span class="${ticket.resolutionOverdue ? 'badge badge-urgent' : 'badge badge-resolved'}">
                                    ${ticket.resolutionOverdue ? 'Resolution overdue' : 'Resolution ok'}
                                </span>
                            </div>
                        </article>
                    `
                        )
                        .join('')}
                </div>
            </article>
            <article class="panel">
                <div class="section-heading">
                    <h2>Uploads</h2>
                    <span class="muted">${state.adminUploads.length} files</span>
                </div>
                <div class="admin-list">
                    ${state.adminUploads
                        .slice(0, 12)
                        .map(
                            (upload) => `
                        <div class="admin-item compact-item">
                            <div>
                                <a href="/${escapeHtml(upload.path)}" target="_blank" rel="noreferrer">
                                    <strong>${escapeHtml(upload.filename)}</strong>
                                </a>
                                <p>${escapeHtml(upload.ticket?.title || 'Unassigned upload')}</p>
                            </div>
                            <div class="status-column">
                                <span class="badge">${escapeHtml(upload.mime_type || 'file')}</span>
                                <button class="danger-button" type="button" data-delete-upload-id="${escapeHtml(upload.id)}">Delete</button>
                            </div>
                        </div>
                    `
                        )
                        .join('')}
                </div>
            </article>
        </section>
    `;
}

function renderAuth() {
    const isRegister = state.authMode === 'register';

    return `
        <section class="auth-shell">
            <div class="auth-hero">
                <p class="eyebrow">Support desk frontend</p>
                <p>
                    Sign in as a user, agent, or admin and the interface adapts to the routes your backend already exposes.
                </p>
                <div class="hero-meta">
                    <span class="hero-chip">Tickets</span>
                    <span class="hero-chip">Comments & Uploads</span>
                    <span class="hero-chip">Agent Queue</span>
                    <span class="hero-chip">Admin Controls</span>
                </div>
            </div>
            <div class="panel auth-panel">
                <div class="section-heading">
                    <h2>${isRegister ? 'Create account' : 'Welcome back'}</h2>
                    <button class="ghost-button" type="button" data-auth-toggle>
                        ${isRegister ? 'I already have an account' : 'Need an account?'}
                    </button>
                </div>
                <form data-form="${isRegister ? 'register' : 'login'}" class="stack-form">
                    ${
                        isRegister
                            ? `
                        <label>
                            <span>Name</span>
                            <input type="text" name="name" placeholder="Jane Support" required />
                        </label>
                    `
                            : ''
                    }
                    <label>
                        <span>Email</span>
                        <input type="email" name="email" placeholder="you@example.com" required />
                    </label>
                    <label>
                        <span>Password</span>
                        <input type="password" name="password" placeholder="Minimum 6 characters" required />
                    </label>
                    ${
                        isRegister
                            ? `
                        <label>
                            <span>Role</span>
                            <select name="role">
                                <option value="user">User</option>
                                <option value="agent">Agent</option>
                            </select>
                        </label>
                        <label>
                            <span>Organization</span>
                            <input type="text" name="organization" placeholder="Operations" required />
                        </label>
                        <label>
                            <span>Category</span>
                            <input type="text" name="category" placeholder="Hardware" />
                        </label>
                    `
                            : ''
                    }
                    <button class="primary-button" type="submit">${isRegister ? 'Create account' : 'Sign in'}</button>
                </form>
            </div>
        </section>
    `;
}

function renderApp() {
    const views = roleViews(state.user.role);
    const activeContent =
        state.view === 'overview'
            ? renderOverview()
            : state.view === 'tickets' || state.view === 'queue'
              ? renderTicketsView()
              : state.view === 'create'
                ? renderCreateView()
                : state.view === 'chat'
                  ? renderChatView()
                  : renderAdminView();

    return `
        <div class="shell">
            <aside class="sidebar">
                <div class="brand-block">
                    <p class="eyebrow">Support Desk</p>
                    <h1>Atlas Console</h1>
                    <span>${escapeHtml(state.user.role)}</span>
                </div>
                <nav class="nav-list">
                    ${views
                        .map(
                            (view) => `
                        <button class="${state.view === view.key ? 'nav-item active' : 'nav-item'}" data-nav="${view.key}">
                            ${escapeHtml(view.label)}
                        </button>
                    `
                        )
                        .join('')}
                </nav>
                <div class="sidebar-footer">
                    <strong>${escapeHtml(state.user.name)}</strong>
                    <p>${escapeHtml(state.user.email)}</p>
                    <button class="ghost-button" type="button" data-action="logout">Sign out</button>
                </div>
            </aside>
            <main class="main-area">
                <header class="topbar">
                    <div>
                        <p class="eyebrow">Backend-aligned frontend</p>
                        <h2>${escapeHtml(
                            state.view === 'queue' ? 'Agent queue' : state.view.charAt(0).toUpperCase() + state.view.slice(1)
                        )}</h2>
                    </div>
                    <div class="topbar-actions">
                        <span class="hero-chip">${escapeHtml(state.tickets.length)} visible tickets</span>
                        <button class="secondary-button" type="button" data-action="refresh-all">Refresh data</button>
                    </div>
                </header>
                ${activeContent}
            </main>
        </div>
    `;
}

function render() {
    const banner = `
        ${state.notice ? `<div class="flash flash-success">${escapeHtml(state.notice)}</div>` : ''}
        ${state.error ? `<div class="flash flash-error">${escapeHtml(state.error)}</div>` : ''}
        ${
            state.loading
                ? `<div class="loading-bar"><span>${escapeHtml(state.loadingLabel || 'Working...')}</span></div>`
                : ''
        }
    `;

    if (state.booting) {
        root.innerHTML = `<div class="boot-screen"><div class="panel"><p class="eyebrow">Loading</p><h1>Booting ticketing frontend...</h1></div></div>`;
        return;
    }

    root.innerHTML = banner + (state.user ? renderApp() : renderAuth());
}

root.addEventListener('click', async (event) => {
    const navTarget = event.target.closest('[data-nav]');

    if (navTarget) {
        state.view = navTarget.dataset.nav;
        state.notice = '';
        state.error = '';
        render();
        return;
    }

    const authToggle = event.target.closest('[data-auth-toggle]');

    if (authToggle) {
        state.authMode = state.authMode === 'login' ? 'register' : 'login';
        state.notice = '';
        state.error = '';
        render();
        return;
    }

    const actionButton = event.target.closest('[data-action]');

    if (actionButton) {
        const action = actionButton.dataset.action;

        if (action === 'logout') {
            await logout();
        } else if (action === 'assign-self') {
            await takeTicket();
        } else if (action === 'escalate-ticket') {
            await escalateTicket();
        } else if (action === 'refresh-all') {
            setLoading(true, 'Refreshing...');
            try {
                await loadAllData();
                flashNotice('Data refreshed.');
            } catch (error) {
                flashError(error.message);
            } finally {
                setLoading(false);
            }
        } else if (action === 'refresh-chat') {
            setLoading(true, 'Refreshing chat...');
            try {
                await loadGeneralChat();
            } finally {
                setLoading(false);
            }
        } else if (action === 'delete-ticket') {
            await deleteTicket();
        }

        return;
    }

    const ticketButton = event.target.closest('[data-ticket-id]');

    if (ticketButton) {
        setLoading(true, 'Loading ticket...');
        try {
            if (ticketButton.dataset.nav) {
                state.view = ticketButton.dataset.nav;
            }
            await loadTicketDetail(ticketButton.dataset.ticketId);
        } catch (error) {
            flashError(error.message);
        } finally {
            setLoading(false);
        }
        return;
    }

    const deleteClientKeyButton = event.target.closest('[data-delete-client-key]');

    if (deleteClientKeyButton) {
        await deleteClientKey(deleteClientKeyButton.dataset.deleteClientKey);
        return;
    }

    const deleteUploadButton = event.target.closest('[data-delete-upload-id]');

    if (deleteUploadButton) {
        await deleteUpload(deleteUploadButton.dataset.deleteUploadId);
    }
});

root.addEventListener('change', async (event) => {
    const filter = event.target.closest('[data-agent-filter]');

    if (filter) {
        state.agentFilter = filter.value;
        setLoading(true, 'Updating queue...');
        try {
            await loadTickets();
        } catch (error) {
            flashError(error.message);
        } finally {
            setLoading(false);
        }
        return;
    }

    const uploadInput = event.target.closest('[data-upload-input]');

    if (uploadInput) {
        await uploadAttachment(uploadInput);
    }
});

root.addEventListener('submit', async (event) => {
    const form = event.target;

    if (!(form instanceof HTMLFormElement)) {
        return;
    }

    event.preventDefault();

    if (form.dataset.form === 'login' || form.dataset.form === 'register') {
        await authenticate(form);
    } else if (form.dataset.form === 'create-ticket') {
        await createTicket(form);
    } else if (form.dataset.form === 'add-comment') {
        await addComment(form);
    } else if (form.dataset.form === 'send-message') {
        await sendMessage(form);
    } else if (form.dataset.form === 'ticket-status') {
        await updateTicketStatus(form);
    } else if (form.dataset.form === 'assign-agents') {
        await assignAgents(form);
    } else if (form.dataset.form === 'update-user-role') {
        await updateUserRole(form);
    } else if (form.dataset.form === 'create-client-key') {
        await createClientKey(form);
    }
});

bootstrapApp();
