(function () {
  function t(key, params) {
    return window.CrashI18n ? window.CrashI18n.t(key, params) : key;
  }

  function basePath() {
    return document.body.getAttribute('data-base-path') || '';
  }

  function escapeHtml(s) {
    return String(s)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;');
  }

  function formatTime(ms) {
    if (!ms) return '—';
    const d = new Date(Number(ms));
    return d.toISOString().replace('T', ' ').slice(0, 19);
  }

  function formatStars(n) {
    const score = Math.max(0, Math.min(5, Number(n) || 0));
    let html =
      '<span class="star-rating" role="img" aria-label="' + score + ' out of 5">';
    for (let i = 1; i <= 5; i++) {
      html += '<span class="star' + (i <= score ? ' star--on' : '') + '"></span>';
    }
    return html + '</span>';
  }

  function renderTagPill(tag) {
    const id = String(tag.id || '').trim();
    const label = escapeHtml(tag.label || tag.id);
    const bg = escapeHtml(tag.bg || '#5c6b82');
    if (!id) {
      return '<span class="report-tag" style="--tag-bg:' + bg + '">' + label + '</span>';
    }
    return (
      '<button type="button" class="report-tag report-tag--filter" data-tag-id="' +
      escapeHtml(id) +
      '" style="--tag-bg:' +
      bg +
      '" title="Filter by tag">' +
      label +
      '</button>'
    );
  }

  function canTagEdit() {
    return document.body.getAttribute('data-can-tag-edit') === '1';
  }

  function initTicketsApp() {
    const app = document.getElementById('tickets-app');
    const tbody = document.getElementById('tickets-tbody');
    const statusEl = document.getElementById('tickets-status');
    const pagination = document.getElementById('tickets-pagination');
    const perPageSel = document.getElementById('tickets-per-page');
    const tagFilter = document.getElementById('tickets-tag-filter');
    const thead = document.querySelector('#tickets-table thead');
    if (!app || !tbody) return;

    let page = 1;
    let perPage = 50;
    let sort = 'opened_at_ms';
    let dir = 'desc';
    let tag = '';

    function load() {
      statusEl.textContent = t('reports.loading');
      const q =
        '?page=' +
        page +
        '&per_page=' +
        perPage +
        '&sort=' +
        encodeURIComponent(sort) +
        '&dir=' +
        encodeURIComponent(dir) +
        (tag ? '&tag=' + encodeURIComponent(tag) : '');
      const xhr = new XMLHttpRequest();
      xhr.open('GET', basePath() + '/api/tickets.php' + q, true);
      xhr.onload = function () {
        let data;
        try {
          data = JSON.parse(xhr.responseText);
        } catch {
          statusEl.textContent = t('reports.invalid_response');
          return;
        }
        if (!data.ok) {
          statusEl.textContent = data.hint || data.error || t('reports.load_failed');
          return;
        }
        renderRows(data.items || []);
        renderPagination(data.total || 0, data.page || 1);
        const from = data.total ? (data.page - 1) * data.per_page + 1 : 0;
        const to = Math.min(data.page * data.per_page, data.total);
        statusEl.textContent = t('reports.status_showing', {
          from,
          to,
          total: data.total,
        });
      };
      xhr.onerror = function () {
        statusEl.textContent = t('reports.network_error');
      };
      xhr.send();
    }

    window.ticketsReloadRef = load;

    function renderRows(items) {
      if (!items.length) {
        tbody.innerHTML =
          '<tr><td colspan="6" class="muted">' + escapeHtml(t('tickets.empty')) + '</td></tr>';
        return;
      }
      let html = '';
      items.forEach((row, i) => {
        const briefId = 'tkt-brief-' + row.id + '-' + i;
        const openUrl = basePath() + '/?view=ticket&id=' + row.id;
        const issueTitle = escapeHtml(row.title || '');
        const issueBrief = row.brief
          ? '<div class="ticket-issue-brief muted">' + escapeHtml(row.brief) + '</div>'
          : '';
        html +=
          '<tr class="report-row report-row--nav" data-href="' +
          escapeHtml(openUrl) +
          '" tabindex="0" role="link">';
        html +=
          '<td class="report-tree-cell"><button type="button" class="report-tree-toggle" aria-expanded="false" aria-controls="' +
          briefId +
          '"><span class="report-tree-arrow"></span></button></td>';
        html +=
          '<td class="ticket-col-issue"><strong class="ticket-issue-title">' +
          issueTitle +
          '</strong>' +
          issueBrief +
          '</td>';
        html += '<td>' + formatTime(row.opened_at_ms) + '</td>';
        html +=
          '<td class="ticket-col-env"><span>' +
          escapeHtml(row.env_brief || '') +
          '</span><br><span class="muted">' +
          escapeHtml(row.device_model || '') +
          '</span></td>';
        html += '<td>' + formatStars(row.rating) + '</td>';
        const tagEditBtn = canTagEdit()
          ? '<button type="button" class="tag-edit-btn" data-ticket-id="' +
            row.id +
            '" title="Edit tags">✎</button>'
          : '';
        const tags = (row.tags || []).map(renderTagPill).join('');
        html +=
          '<td class="col-tags"><div class="report-tags">' +
          tags +
          tagEditBtn +
          '</div></td>';
        html += '</tr>';
        html +=
          '<tr class="report-brief-row" id="' +
          briefId +
          '" hidden><td colspan="6"><div class="report-brief-panel report-row--nav" data-href="' +
          escapeHtml(openUrl) +
          '" tabindex="0" role="link"><p class="muted">' +
          escapeHtml(t('row.open_report')) +
          '</p><ul class="report-brief-lines">';
        [row.brief, row.env_brief, 'Owner: ' + (row.owner_username || '—')]
          .filter(Boolean)
          .forEach((line) => {
            html += '<li>' + escapeHtml(String(line)) + '</li>';
          });
        html += '</ul></div></td></tr>';
      });
      tbody.innerHTML = html;
      bindRows();
    }

    function applyTagFilter(tagId) {
      tag = tagId;
      if (tagFilter) {
        let found = false;
        tagFilter.querySelectorAll('option').forEach((opt) => {
          if (opt.value === tagId) found = true;
        });
        if (!found) {
          const opt = document.createElement('option');
          opt.value = tagId;
          opt.textContent = tagId;
          tagFilter.appendChild(opt);
        }
        tagFilter.value = tagId;
      }
      page = 1;
      load();
    }

    function activateTag(tagId, ev) {
      if (!tagId) return;
      ev.stopPropagation();
      ev.preventDefault();
      const xhr = new XMLHttpRequest();
      xhr.open(
        'GET',
        basePath() +
          '/api/tickets.php?page=1&per_page=2&tag=' +
          encodeURIComponent(tagId),
        true
      );
      xhr.onload = function () {
        let data;
        try {
          data = JSON.parse(xhr.responseText);
        } catch {
          return;
        }
        if (!data.ok) return;
        const total = Number(data.total || 0);
        if (total === 1 && data.items && data.items[0] && data.items[0].id) {
          window.location.href =
            basePath() + '/?view=ticket&id=' + encodeURIComponent(String(data.items[0].id));
          return;
        }
        applyTagFilter(tagId);
      };
      xhr.send();
    }

    function bindRows() {
      tbody.querySelectorAll('.report-tree-toggle').forEach((btn) => {
        btn.addEventListener('click', (e) => {
          e.stopPropagation();
          e.preventDefault();
          const controls = btn.getAttribute('aria-controls');
          const row = controls ? document.getElementById(controls) : null;
          if (!row) return;
          const open = row.hidden;
          row.hidden = !open;
          btn.setAttribute('aria-expanded', open ? 'true' : 'false');
        });
      });
      tbody.querySelectorAll('[data-href]').forEach((el) => {
        const href = el.getAttribute('data-href');
        if (!href) return;
        const go = () => {
          window.location.href = href;
        };
        el.addEventListener('click', (e) => {
          if (e.target.closest('.report-tree-toggle, .tag-edit-btn, .report-tag--filter')) return;
          go();
        });
        el.addEventListener('keydown', (e) => {
          if (e.target.closest('.report-tree-toggle, .tag-edit-btn, .report-tag--filter')) return;
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            go();
          }
        });
      });
      tbody.querySelectorAll('.tag-edit-btn').forEach((btn) => {
        btn.addEventListener('click', (e) => {
          e.stopPropagation();
          e.preventDefault();
          if (typeof window.openTagModal === 'function') {
            window.openTagModal(Number(btn.getAttribute('data-ticket-id')), 'ticket');
          }
        });
      });
      tbody.querySelectorAll('.report-tag--filter').forEach((btn) => {
        btn.addEventListener('click', (e) => {
          activateTag(btn.getAttribute('data-tag-id') || '', e);
        });
      });
    }

    function renderPagination(total, currentPage) {
      if (!pagination) return;
      page = currentPage;
      const pages = Math.max(1, Math.ceil(total / perPage));
      const prev = page > 1 ? page - 1 : null;
      const next = page < pages ? page + 1 : null;
      let html = '<div class="pagination-inner">';
      html +=
        '<button type="button" class="btn page-btn" data-page="' +
        (prev || '') +
        '" ' +
        (prev ? '' : 'disabled') +
        '>← Previous</button>';
      html +=
        '<span class="page-info">Page ' +
        page +
        ' / ' +
        pages +
        ' · ' +
        total +
        ' tickets</span>';
      html +=
        '<button type="button" class="btn page-btn" data-page="' +
        (next || '') +
        '" ' +
        (next ? '' : 'disabled') +
        '>Next →</button></div>';
      pagination.innerHTML = html;
      pagination.querySelectorAll('.page-btn').forEach((btn) => {
        btn.addEventListener('click', () => {
          const p = Number(btn.getAttribute('data-page'));
          if (!p) return;
          page = p;
          load();
        });
      });
    }

    if (perPageSel) {
      perPageSel.addEventListener('change', () => {
        perPage = Number(perPageSel.value) || 50;
        page = 1;
        load();
      });
    }
    if (tagFilter) {
      tagFilter.addEventListener('change', () => {
        tag = tagFilter.value || '';
        page = 1;
        load();
      });
    }
    if (thead) {
      thead.querySelectorAll('.sortable').forEach((th) => {
        th.addEventListener('click', () => {
          const key = th.getAttribute('data-sort');
          if (!key) return;
          if (sort === key) {
            dir = dir === 'asc' ? 'desc' : 'asc';
          } else {
            sort = key;
            dir = 'desc';
          }
          thead.querySelectorAll('.sortable').forEach((x) => {
            x.classList.toggle('sortable--active', x === th);
          });
          page = 1;
          load();
        });
      });
    }

    window.__ticketsReload = function () {
      page = 1;
      load();
    };

    load();
  }

  function onReady(fn) {
    if (window.CrashI18n && window.CrashI18n.ready) {
      window.CrashI18n.ready.then(fn);
    } else {
      fn();
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => onReady(initTicketsApp));
  } else {
    onReady(initTicketsApp);
  }
})();
