const token = location.pathname.split('/').pop();
history.replaceState(null, '', '/admin');

const grid = document.querySelector('#review-grid');
const reviewStatus = document.querySelector('#review-status');
const reviewCount = document.querySelector('#review-count');
const selected = new Set();

document.querySelector('#refresh-review').addEventListener('click', loadPending);
document.querySelector('#approve-selected').addEventListener('click', () => moderateSelected('approve'));
document.querySelector('#delete-selected').addEventListener('click', () => moderateSelected('delete'));

grid.addEventListener('change', (event) => {
  const checkbox = event.target.closest('[data-select-id]');
  if (!checkbox) return;
  if (checkbox.checked) selected.add(checkbox.dataset.selectId);
  else selected.delete(checkbox.dataset.selectId);
});

grid.addEventListener('click', (event) => {
  const action = event.target.closest('[data-admin-action]');
  if (!action) return;
  moderate([action.dataset.id], action.dataset.adminAction);
});

await loadPending();

async function loadPending() {
  selected.clear();
  reviewStatus.textContent = 'FETCHING_PENDING_QUEUE';
  const response = await fetch('/api/admin/pending', { headers: adminHeaders() });
  const payload = await response.json();
  if (!response.ok) {
    reviewStatus.textContent = 'REVIEW_AUTH_FAILED';
    grid.innerHTML = '<div class="empty-state">ADMIN_TOKEN_INVALID</div>';
    return;
  }
  reviewStatus.textContent = 'PENDING_REVIEW';
  reviewCount.textContent = `${payload.total} ITEMS`;
  renderPending(payload.memes);
}

function renderPending(memes) {
  if (memes.length === 0) {
    grid.innerHTML = '<div class="empty-state">NO_PENDING_MEMES</div>';
    return;
  }

  grid.replaceChildren(...memes.map((meme) => {
    const article = document.createElement('article');
    article.className = 'meme-card';
    article.innerHTML = `
      <div class="card-head">
        <label class="review-select">
          <input type="checkbox" data-select-id="${meme.id}">
          <span>ID: ${shortId(meme.id)}</span>
        </label>
        <span class="card-meta age">SCORE ${meme.moderationScore}</span>
      </div>
      <div class="image-frame">
        <img src="/admin-media/${token}/${meme.id}" alt="Pending meme ${shortId(meme.id)}" loading="lazy">
      </div>
      <div class="review-body">
        <p>${escapeText(meme.moderationReason || 'Queued for review.')}</p>
      </div>
      <div class="card-actions">
        <div class="stats">
          <span class="card-stat">${formatBytes(meme.byteSize)}</span>
        </div>
        <div class="action-group">
          <button class="text-action text-action-accent icon-only-action" type="button" data-admin-action="approve" data-id="${meme.id}" aria-label="Approve meme" title="Approve meme"><span class="material-symbols-outlined" aria-hidden="true">check</span></button>
          <button class="text-action icon-only-action danger-action" type="button" data-admin-action="delete" data-id="${meme.id}" aria-label="Delete meme" title="Delete meme"><span class="material-symbols-outlined" aria-hidden="true">delete</span></button>
        </div>
      </div>
    `;
    return article;
  }));
}

async function moderateSelected(action) {
  if (selected.size === 0) return;
  await moderate([...selected], action);
}

async function moderate(ids, action) {
  const endpoint = action === 'approve' ? '/api/admin/approve' : '/api/admin/delete';
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: { ...adminHeaders(), 'Content-Type': 'application/json' },
    body: JSON.stringify({ ids })
  });
  if (!response.ok) {
    reviewStatus.textContent = 'REVIEW_ACTION_FAILED';
    return;
  }
  await loadPending();
}

function adminHeaders() {
  return { 'X-Admin-Token': token };
}

function shortId(id) {
  return `0x${id.slice(0, 4).toUpperCase()}...${id.slice(-4).toUpperCase()}`;
}

function formatBytes(value) {
  if (value >= 1024 * 1024) return `${(value / 1024 / 1024).toFixed(1)}MB`;
  return `${Math.ceil(value / 1024)}KB`;
}

function escapeText(value) {
  const span = document.createElement('span');
  span.textContent = value;
  return span.innerHTML;
}
