(() => {
  const endpoint = window.PROOFREAD_ENDPOINT;
  if (!endpoint) return;

  const csrfNameEl = document.getElementById('proofreadCsrfName');
  const csrfHashEl = document.getElementById('proofreadCsrfHash');

  const resize = (el) => {
    if (!el) return;
    el.style.height = 'auto';
    el.style.height = `${el.scrollHeight}px`;
  };

  const isSafeMatch = (m) => {
    const issueType = (m.rule?.issueType || '').toLowerCase();
    const repl = m.replacements || [];
    if (repl.length !== 1) return false;

    const len = m.length ?? 0;
    if (len > 25) return false;

    if (issueType === 'misspelling') return true;

    const msg = (m.message || '').toLowerCase();
    if (msg.includes('whitespace') || msg.includes('space') || msg.includes('punctuation')) return true;

    return false;
  };

  const applyMatches = (text, matches) => {
    const sorted = [...matches].sort((a, b) => (b.offset || 0) - (a.offset || 0));
    let out = text;

    for (const m of sorted) {
      const offset = m.offset || 0;
      const length = m.length || 0;
      const repl = m.replacements?.[0]?.value;
      if (typeof repl !== 'string') continue;

      out = out.slice(0, offset) + repl + out.slice(offset + length);
    }
    return out;
  };

  const refreshCsrf = (hash) => {
    if (!hash) return;
    if (csrfHashEl) csrfHashEl.value = hash;
    const name = csrfNameEl ? csrfNameEl.value : null;
    if (!name) return;
    document.querySelectorAll(`input[name="${name}"]`).forEach((el) => {
      el.value = hash;
    });
  };

  const setStatus = (targetId, message, isError = false) => {
    const status = document.querySelector(`[data-status-for="${targetId}"]`);
    if (!status) return;
    status.textContent = message;
    status.classList.toggle('text-danger', !!isError);
  };

  const clearList = (targetId) => {
    const list = document.querySelector(`[data-list-for="${targetId}"]`);
    if (list) list.innerHTML = '';
  };

  const renderRisky = (targetId, risky, textarea) => {
    const list = document.querySelector(`[data-list-for="${targetId}"]`);
    if (!list) return;
    list.innerHTML = '';

    risky.forEach((match) => {
      const li = document.createElement('li');
      li.className = 'mb-1';

      const suggestion = match.replacements?.[0]?.value || '(no suggestion)';
      const label = document.createElement('span');
      label.textContent = `${match.message || 'Suggestion'} → ${suggestion}`;

      const btn = document.createElement('button');
      btn.type = 'button';
      btn.className = 'btn btn-link btn-sm ps-0';
      btn.textContent = 'Apply';
      btn.addEventListener('click', () => {
        textarea.value = applyMatches(textarea.value, [match]);
        resize(textarea);
        textarea.dispatchEvent(new Event('input', { bubbles: true }));
        li.remove();
      });

      li.appendChild(label);
      li.appendChild(document.createTextNode(' '));
      li.appendChild(btn);
      list.appendChild(li);
    });
  };

  const proofreadField = async (textarea) => {
    if (!textarea) return { ok: false };
    const targetId = textarea.id || textarea.name || '';

    const text = textarea.value || '';
    if (!text.trim()) {
      setStatus(targetId, 'Enter text to proofread.', true);
      clearList(targetId);
      return { ok: false };
    }

    setStatus(targetId, 'Checking...');
    clearList(targetId);

    const body = new URLSearchParams();
    body.append('text', text);
    const name = csrfNameEl ? csrfNameEl.value : null;
    const hash = csrfHashEl ? csrfHashEl.value : null;
    if (name && hash) body.append(name, hash);

    let data;
    try {
      const resp = await fetch(endpoint, {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body,
      });
      data = await resp.json();
    } catch (err) {
      setStatus(targetId, 'Network error.', true);
      return { ok: false, error: 'Network error.' };
    }

    refreshCsrf(data?.csrfHash);

    if (!data || !data.ok) {
      setStatus(targetId, data?.error || 'Proofread failed.', true);
      return { ok: false, error: data?.error || 'Proofread failed.' };
    }

    const matches = data.result?.matches || [];
    if (!matches.length) {
      setStatus(targetId, 'No issues found.');
      return { ok: true, safe: 0, risky: 0 };
    }

    const safe = matches.filter(isSafeMatch);
    const risky = matches.filter((m) => !isSafeMatch(m));

    const updated = applyMatches(text, safe);
    if (updated !== text) {
      textarea.value = updated;
      resize(textarea);
      textarea.dispatchEvent(new Event('input', { bubbles: true }));
    }

    renderRisky(targetId, risky, textarea);
    setStatus(targetId, `Auto-fixed: ${safe.length}. Needs review: ${risky.length}.`);
    return { ok: true, safe: safe.length, risky: risky.length };
  };

  const proofreadAll = async () => {
    const btn = document.getElementById('proofreadAllBtn');
    const summary = document.getElementById('proofreadAllStatus');
    const fields = Array.from(document.querySelectorAll('textarea.review-field'));
    if (!fields.length) return;

    if (btn) btn.disabled = true;
    if (summary) summary.textContent = 'Checking all reviews...';

    let totalSafe = 0;
    let totalRisky = 0;
    let errors = 0;

    for (const field of fields) {
      const result = await proofreadField(field);
      if (result?.safe) totalSafe += result.safe;
      if (result?.risky) totalRisky += result.risky;
      if (!result?.ok) errors += 1;
    }

    if (summary) {
      summary.textContent = `Auto-fixed: ${totalSafe}. Needs review: ${totalRisky}. ${errors ? 'Errors on ' + errors + ' field(s).' : ''}`;
    }
    if (btn) btn.disabled = false;
  };

  document.addEventListener('DOMContentLoaded', () => {
    const btn = document.getElementById('proofreadAllBtn');
    if (btn) btn.addEventListener('click', proofreadAll);
  });
})();
