// panes/items.js — CRUD against /api/items with search, bulk select, export/import.
import { registerPane } from '../app.js';
import { jget, jpost, jdelete, escapeHtml } from '../lib/api.js';
import { ok, err, copyToClipboard, fmtJSON } from '../lib/ui.js';

const TPL = `
  <div class="pane-head">
    <div><div class="title">Items</div><div class="sub">Backend-managed records · <code>/api/items</code>.</div></div>
    <div class="grow"></div>
    <button class="btn btn-secondary" id="items-export">Export</button>
    <button class="btn btn-secondary" id="items-import">Import</button>
    <button class="btn btn-secondary" id="items-refresh">Refresh</button>
  </div>

  <div class="grid" style="grid-template-columns: 360px 1fr; gap: 16px;">
    <div class="card">
      <div class="card-title"><h2>New item</h2></div>
      <form id="items-form" class="grid gap-3">
        <label class="field"><span class="lbl">Name</span><input class="input" id="items-name" required maxlength="120"/></label>
        <label class="field"><span class="lbl">Description</span><textarea class="input" id="items-desc" rows="4" maxlength="2000"></textarea></label>
        <div class="btn-row">
          <button class="btn btn-primary" type="submit">Add</button>
          <button class="btn btn-ghost" type="reset">Clear</button>
        </div>
      </form>

      <div class="divider"></div>

      <div class="card-title"><h2 style="font-size:14px">Bulk actions</h2><span class="muted xsmall" id="items-sel-count">0 selected</span></div>
      <div class="btn-row">
        <button class="btn btn-secondary" id="items-sel-all">Select all</button>
        <button class="btn btn-secondary" id="items-sel-none">Clear</button>
        <button class="btn btn-danger" id="items-sel-del" disabled>Delete selected</button>
      </div>
    </div>

    <div class="card">
      <div class="card-title">
        <h2>Records <span class="muted mono xsmall" id="items-count">—</span></h2>
        <input class="input" id="items-search" placeholder="filter…" style="max-width:240px"/>
      </div>
      <div id="items-list" class="scroll" style="max-height:62vh">loading…</div>
    </div>
  </div>

  <input type="file" id="items-file" accept=".json" style="display:none"/>
`;

let all = [];
const selected = new Set();

function row(it, checked) {
  return `<div class="row" data-id="${it.id}">
    <label class="check"><input type="checkbox" data-sel="${it.id}" ${checked ? 'checked' : ''}/></label>
    <span class="mono muted">#${it.id}</span>
    <div class="grow">
      <div class="ttl"><span data-edit="name-${it.id}">${escapeHtml(it.name)}</span></div>
      <div class="desc"><span data-edit="desc-${it.id}">${escapeHtml(it.description || '')}</span></div>
    </div>
    <button class="btn btn-ghost" data-copy="${it.id}" title="Copy as JSON"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg></button>
    <span class="act" data-del="${it.id}">delete</span>
  </div>`;
}

function render(host) {
  const q = host.querySelector('#items-search').value.trim().toLowerCase();
  const filtered = q ? all.filter(it => (it.name + ' ' + (it.description || '')).toLowerCase().includes(q)) : all;
  host.querySelector('#items-count').textContent = `${filtered.length}/${all.length}`;
  host.querySelector('#items-list').innerHTML = filtered.length
    ? filtered.map(it => row(it, selected.has(it.id))).join('')
    : '<div class="muted" style="padding:16px">no items match</div>';

  host.querySelectorAll('[data-del]').forEach(b => b.addEventListener('click', async () => {
    if (!confirm(`Delete item #${b.dataset.del}?`)) return;
    try { await jdelete('/api/items/' + b.dataset.del); selected.delete(+b.dataset.del); await load(host); ok('deleted'); }
    catch (e) { err(e.message); }
  }));
  host.querySelectorAll('[data-copy]').forEach(b => b.addEventListener('click', () => {
    const it = all.find(x => x.id === +b.dataset.copy); if (it) copyToClipboard(fmtJSON(it), 'copied');
  }));
  host.querySelectorAll('[data-sel]').forEach(c => c.addEventListener('change', () => {
    const id = +c.dataset.sel;
    if (c.checked) selected.add(id); else selected.delete(id);
    updateSel(host);
  }));
}

function updateSel(host) {
  host.querySelector('#items-sel-count').textContent = `${selected.size} selected`;
  host.querySelector('#items-sel-del').disabled = selected.size === 0;
}

async function load(host) {
  try {
    const j = await jget('/api/items');
    all = j.items || [];
    // prune stale selections
    const ids = new Set(all.map(x => x.id));
    for (const id of [...selected]) if (!ids.has(id)) selected.delete(id);
    render(host); updateSel(host);
  } catch (e) {
    host.querySelector('#items-list').innerHTML = `<div class="muted" style="padding:16px">${escapeHtml(e.message)}</div>`;
  }
}

registerPane('items', {
  label: 'Items',
  init(host) {
    host.innerHTML = TPL;
    host.querySelector('#items-refresh').addEventListener('click', () => load(host));
    host.querySelector('#items-search').addEventListener('input', () => render(host));
    host.querySelector('#items-form').addEventListener('submit', async (e) => {
      e.preventDefault();
      const name = host.querySelector('#items-name').value.trim();
      const description = host.querySelector('#items-desc').value.trim();
      if (!name) return;
      try {
        await jpost('/api/items', { name, description });
        host.querySelector('#items-form').reset();
        ok('added'); await load(host);
      } catch (e) { err(e.message); }
    });

    host.querySelector('#items-sel-all').addEventListener('click', () => { all.forEach(x => selected.add(x.id)); render(host); updateSel(host); });
    host.querySelector('#items-sel-none').addEventListener('click', () => { selected.clear(); render(host); updateSel(host); });
    host.querySelector('#items-sel-del').addEventListener('click', async () => {
      const ids = [...selected];
      if (!ids.length) return;
      if (!confirm(`Delete ${ids.length} item(s)?`)) return;
      for (const id of ids) { try { await jdelete('/api/items/' + id); } catch (e) { err(`#${id}: ${e.message}`); } }
      selected.clear(); ok(`deleted ${ids.length}`); await load(host);
    });

    host.querySelector('#items-export').addEventListener('click', () => {
      const blob = new Blob([JSON.stringify(all, null, 2)], { type: 'application/json' });
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = `cxwebapp-items-${new Date().toISOString().slice(0, 10)}.json`;
      a.click();
      setTimeout(() => URL.revokeObjectURL(a.href), 1000);
    });
    host.querySelector('#items-import').addEventListener('click', () => host.querySelector('#items-file').click());
    host.querySelector('#items-file').addEventListener('change', async (e) => {
      const f = e.target.files?.[0]; if (!f) return;
      try {
        const text = await f.text();
        const arr = JSON.parse(text);
        if (!Array.isArray(arr)) throw new Error('expected JSON array');
        let n = 0;
        for (const it of arr) {
          if (!it?.name) continue;
          try { await jpost('/api/items', { name: it.name, description: it.description || '' }); n++; } catch {}
        }
        ok(`imported ${n}/${arr.length}`); await load(host);
      } catch (err2) { err('import: ' + err2.message); }
      e.target.value = '';
    });

    load(host);
  },
  refresh: load,
});
