// ─────────────────────────────────────────────
// DEV_Design_ListView.jsx  (V7)
// ListViewPanel + HomeCanvas
// Depends on: SDS styles (DEV_Design.jsx)
// V7: field_id/field_code, display:'list'|'card'
// ─────────────────────────────────────────────
function ListViewPanel({ fields, cfg, schema, app, onChange }) {
  const activeFields = (fields || []).filter(f => f.status !== 0);

  const initSelected = () => {
    if (cfg?.fields?.length) return cfg.fields.map(f => ({ ...f }));
    return activeFields.slice(0, 4).map(f => ({
      field_id: f.id, field_code: f.code, label: f.name, width: 2,
    }));
  };

  const [selected,  setSelected]  = React.useState(initSelected);
  const [pagesize,  setPagesize]  = React.useState(cfg?.pagesize  || 50);
  const [sortfield, setSortfield] = React.useState(cfg?.sortfield || 'r_auto');
  const [sortdir,   setSortdir]   = React.useState(cfg?.sortdir   || 'asc');
  const [display,   setDisplay]   = React.useState(cfg?.display   || 'list');
  const [editable,  setEditable]  = React.useState(cfg?.editable  ?? false);
  const dragRef = React.useRef(null);
  const [dragIdx,  setDragIdx]  = React.useState(null);
  const [dragOver, setDragOver] = React.useState(null);
  const [previewRows, setPreviewRows] = React.useState([]);
  const [previewLoad, setPreviewLoad] = React.useState(false);

  const available = activeFields.filter(f => !selected.find(s => s.field_code === f.code));

  // Fetch preview records when fields/sort change
  const fieldKey = selected.map(s => s.field_code).join(',');
  React.useEffect(() => {
    const tCode = schema?.code;
    if (!tCode || !selected.length || !app?.app_id) { setPreviewRows([]); return; }
    setPreviewLoad(true);
    const params = new URLSearchParams({
      app: app.app_id, table: tCode, fields: fieldKey,
      limit: 8, offset: 0, sort: sortfield, dir: sortdir,
    });
    apiFetch(`${API_BASE}/v6/records?${params}`)
      .then(r => r.json())
      .then(d => { if (d.status === 'ok') setPreviewRows(d.records || []); })
      .catch(() => {})
      .finally(() => setPreviewLoad(false));
  }, [schema?.code, fieldKey, sortfield, sortdir]);

  function emit(sel, ps, sf, sd, disp, edit) {
    onChange({ fields:sel, pagesize:ps, sortfield:sf, sortdir:sd, display:disp, editable:edit });
  }

  function addField(code) {
    const f = activeFields.find(f => f.code === code);
    if (!f) return;
    const next = [...selected, { field_id:f.id, field_code:f.code, label:f.name, width:2 }];
    setSelected(next);
    emit(next, pagesize, sortfield, sortdir, display, editable);
  }

  function removeField(idx) {
    const next = selected.filter((_, i) => i !== idx);
    setSelected(next);
    emit(next, pagesize, sortfield, sortdir, display, editable);
  }

  function updateField(idx, key, val) {
    const next = selected.map((s, i) => i === idx ? { ...s, [key]: val } : s);
    setSelected(next);
    emit(next, pagesize, sortfield, sortdir, display, editable);
  }

  function onDragStart(idx) { dragRef.current = idx; setDragIdx(idx); }
  function onDragEnter(idx) { setDragOver(idx); }
  function onDragEnd() {
    if (dragRef.current !== null && dragOver !== null && dragRef.current !== dragOver) {
      const next = [...selected];
      const [moved] = next.splice(dragRef.current, 1);
      next.splice(dragOver, 0, moved);
      setSelected(next);
      emit(next, pagesize, sortfield, sortdir, display, editable);
    }
    dragRef.current = null; setDragIdx(null); setDragOver(null);
  }

  const tName = (schema?.name || schema?.code || '').toUpperCase();

  return (
    <div style={{ padding:'14px 0' }}>

      {/* ── Control bar ── */}
      <div style={{ display:'flex', alignItems:'flex-end', gap:20,
                    padding:'0 0 14px', borderBottom:'1px solid #f1f5f9',
                    flexWrap:'wrap' }}>

        <div>
          <div style={SDS.lvCtrlLabel}>Add Field</div>
          <select onChange={e => { if (e.target.value) { addField(e.target.value); e.target.value=''; } }}
            style={SDS.lvSelect}>
            <option value="">— select field —</option>
            {available.map(f => (
              <option key={f.id} value={f.code}>{f.name} ({f.code})</option>
            ))}
          </select>
        </div>

        <div>
          <div style={SDS.lvCtrlLabel}>Rows / Page</div>
          <select value={pagesize}
            onChange={e => { const v=Number(e.target.value); setPagesize(v); emit(selected,v,sortfield,sortdir,display,editable); }}
            style={{ ...SDS.lvSelect, width:80 }}>
            {[10,25,50,100,250].map(n => <option key={n} value={n}>{n}</option>)}
          </select>
        </div>

        <div>
          <div style={SDS.lvCtrlLabel}>Default Sort</div>
          <select value={sortfield}
            onChange={e => { setSortfield(e.target.value); emit(selected,pagesize,e.target.value,sortdir,display,editable); }}
            style={SDS.lvSelect}>
            <option value="r_auto">Record #</option>
            {activeFields.map(f => <option key={f.id} value={f.code}>{f.name}</option>)}
          </select>
        </div>

        <div>
          <div style={SDS.lvCtrlLabel}>Direction</div>
          <div style={{ display:'flex', gap:6 }}>
            {[['asc','↑ A–Z'],['desc','↓ Z–A']].map(([v,l]) => (
              <button key={v} onClick={() => { setSortdir(v); emit(selected,pagesize,sortfield,v,display,editable); }}
                style={{ padding:'5px 12px', border:'1.5px solid',
                         borderColor: sortdir===v ? '#2563eb' : '#e2e8f0',
                         borderRadius:6, fontSize:12, fontWeight: sortdir===v ? 700 : 400,
                         cursor:'pointer', fontFamily:'DM Sans, sans-serif',
                         background: sortdir===v ? '#eff6ff' : '#fff',
                         color: sortdir===v ? '#2563eb' : '#374151' }}>
                {l}
              </button>
            ))}
          </div>
        </div>

        <div>
          <div style={SDS.lvCtrlLabel}>Display Mode</div>
          <select value={display}
            onChange={e => { setDisplay(e.target.value); emit(selected,pagesize,sortfield,sortdir,e.target.value,editable); }}
            style={{ ...SDS.lvSelect, width:100 }}>
            <option value="list">📋 List</option>
            <option value="card">🃏 Cards</option>
          </select>
        </div>

        <div style={{ paddingBottom:4 }}>
          <label style={{ display:'flex', alignItems:'center', gap:7, fontSize:12,
                          color:'#374151', cursor:'pointer', userSelect:'none' }}>
            <input type="checkbox" checked={editable}
              onChange={e => { setEditable(e.target.checked); emit(selected,pagesize,sortfield,sortdir,display,e.target.checked); }}
              style={{ width:14, height:14, cursor:'pointer' }} />
            Allow Editing in List View
          </label>
        </div>
      </div>

      {/* ── Field rows ── */}
      <div style={{ marginTop:14 }}>
        <div style={{ display:'flex', alignItems:'center', padding:'6px 12px',
                      fontSize:10, fontWeight:700, color:'#94a3b8',
                      letterSpacing:'0.07em', textTransform:'uppercase', gap:8 }}>
          <span style={{ flex:'0 0 20px' }}></span>
          <span style={{ flex:'0 0 130px' }}>Field</span>
          <span style={{ flex:1 }}>Column Label</span>
          <span style={{ flex:'0 0 160px', textAlign:'right' }}>Relative Width</span>
          <span style={{ flex:'0 0 30px' }}></span>
        </div>

        {selected.length === 0 && (
          <div style={{ padding:'20px 12px', fontSize:13, color:'#94a3b8',
                        textAlign:'center', border:'1px dashed #e2e8f0',
                        borderRadius:8, margin:'0 0 8px' }}>
            Use "Add Field" above to add columns to your list view
          </div>
        )}

        {selected.map((s, idx) => {
          const schemaField = activeFields.find(f => f.code === s.field_code);
          return (
            <div key={s.field_code} draggable
              onDragStart={() => onDragStart(idx)}
              onDragEnter={() => onDragEnter(idx)}
              onDragEnd={onDragEnd}
              onDragOver={e => e.preventDefault()}
              style={{ display:'flex', alignItems:'center', gap:8, padding:'8px 12px',
                       borderBottom:'1px solid #f1f5f9', fontSize:13,
                       background: dragOver===idx ? '#eff6ff' : '#fff',
                       cursor:'grab' }}>
              <span style={{ flex:'0 0 20px', color:'#cbd5e1', fontSize:14 }}>⠿</span>
              <span style={{ flex:'0 0 130px' }}>
                <span style={{ fontFamily:'DM Mono, monospace', fontSize:11,
                               color:'#94a3b8', marginRight:6 }}>
                  {s.field_code}
                </span>
                <span style={{ fontSize:12, color:'#374151' }}>
                  {schemaField?.name || ''}
                </span>
              </span>
              <input value={s.label || ''}
                onChange={e => updateField(idx, 'label', e.target.value)}
                style={{ flex:1, padding:'5px 8px', border:'1.5px solid #e2e8f0',
                         borderRadius:6, fontSize:13, fontFamily:'DM Sans, sans-serif',
                         outline:'none', color:'#0f1923' }} />
              <div style={{ flex:'0 0 160px', display:'flex',
                            justifyContent:'flex-end', gap:4 }}>
                {[1,2,3,4].map(n => (
                  <button key={n} onClick={() => updateField(idx, 'width', n)}
                    style={{ width:28, height:28, borderRadius:6,
                             border: s.width===n ? '2px solid #2563eb' : '1.5px solid #e2e8f0',
                             background: s.width===n ? '#eff6ff' : '#fff',
                             color: s.width===n ? '#2563eb' : '#374151',
                             fontSize:12, fontWeight: s.width===n ? 700 : 400,
                             cursor:'pointer', fontFamily:'DM Sans, sans-serif' }}>
                    {n}
                  </button>
                ))}
              </div>
              <button onClick={() => removeField(idx)}
                style={{ flex:'0 0 30px', background:'none', border:'none',
                         color:'#dc2626', cursor:'pointer', fontSize:16,
                         opacity:0.6 }}>✕</button>
            </div>
          );
        })}
      </div>

      {/* ── Preview ── */}
      {selected.length > 0 && (
        <div style={{ marginTop:24 }}>
          <div style={{ display:'flex', alignItems:'center',
                        justifyContent:'space-between', marginBottom:8 }}>
            <div style={{ fontSize:11, fontWeight:700, color:'#94a3b8',
                          letterSpacing:'0.07em', textTransform:'uppercase' }}>
              Preview — {tName}
            </div>
            <div style={{ fontSize:11, color:'#94a3b8' }}>
              {previewLoad ? 'Loading…' : `${previewRows.length} sample records`}
            </div>
          </div>
          <div style={{ border:'1px solid #e2e8f0', borderRadius:8, overflow:'hidden' }}>
            <div style={{ display:'flex', alignItems:'center', background:'#f8fafc',
                          padding:'8px 12px', borderBottom:'1px solid #e2e8f0' }}>
              {selected.map(s => (
                <div key={s.field_code}
                  style={{ flex: s.width||2, fontSize:12, fontWeight:700,
                           color:'#374151', overflow:'hidden',
                           textOverflow:'ellipsis', whiteSpace:'nowrap', paddingRight:8 }}>
                  {s.label || s.field_code}
                </div>
              ))}
              <div style={{ flex:'0 0 24px' }}></div>
            </div>
            {previewLoad && (
              <div style={{ padding:'16px', textAlign:'center',
                            color:'#94a3b8', fontSize:12 }}>Loading preview…</div>
            )}
            {!previewLoad && previewRows.length === 0 && (
              <div style={{ padding:'16px', textAlign:'center',
                            color:'#94a3b8', fontSize:12 }}>No records found</div>
            )}
            {!previewLoad && previewRows.map((row, ri) => (
              <div key={ri}
                style={{ display:'flex', alignItems:'center', padding:'8px 12px',
                         borderTop: ri > 0 ? '1px solid #f1f5f9' : 'none',
                         fontSize:13, color:'#0f1923' }}>
                {selected.map(s => {
                  const val = row[s.field_code] || null;
                  return (
                    <div key={s.field_code}
                      style={{ flex: s.width||2, overflow:'hidden',
                               textOverflow:'ellipsis', whiteSpace:'nowrap',
                               paddingRight:8, color: val ? '#0f1923' : '#cbd5e1' }}>
                      {val || '—'}
                    </div>
                  );
                })}
                <div style={{ flex:'0 0 24px', color:'#2563eb',
                              fontSize:12, textAlign:'right' }}>▶</div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────
// V7 HomeCanvas — table visibility/sort
// Uses V7 schema field names (_oid, code, sort, show, link)
// ─────────────────────────────────────────────
function HomeCanvas({ tables, selectedOid, onSelectTable, onReorder }) {
  const [local,   setLocal]   = React.useState(() => [...tables].sort((a,b) => (a.sort||99)-(b.sort||99)));
  const [dragIdx, setDragIdx] = React.useState(null);
  const [overIdx, setOverIdx] = React.useState(null);
  const dragRef = React.useRef(null);

  React.useEffect(() => {
    setLocal([...tables].sort((a,b) => (a.sort||99)-(b.sort||99)));
  }, [tables.map(t => t._oid+t.name+t.show+t.sort).join(',')]);

  function onDragStart(idx) { dragRef.current = idx; setDragIdx(idx); }
  function onDragEnter(idx) { setOverIdx(idx); }
  function onDragEnd() {
    if (dragRef.current !== null && overIdx !== null && dragRef.current !== overIdx) {
      const next = [...local];
      const [moved] = next.splice(dragRef.current, 1);
      next.splice(overIdx, 0, moved);
      next.forEach((t, i) => { t.sort = i + 1; });
      setLocal(next);
      onReorder && onReorder(next);
    }
    dragRef.current = null; setDragIdx(null); setOverIdx(null);
  }

  if (!local.length) return (
    <div style={{ padding:40, textAlign:'center', color:'#94a3b8', fontSize:13 }}>
      No tables yet — create one in the Database tab first.
    </div>
  );

  const visCount = local.filter(t => t.show !== false).length;

  return (
    <div>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between',
                    marginBottom:14 }}>
        <div style={{ fontSize:12, fontWeight:700, color:'#64748b',
                      textTransform:'uppercase', letterSpacing:'0.06em' }}>
          Home Page · {visCount} visible {visCount === 1 ? 'table' : 'tables'}
        </div>
        <div style={{ fontSize:11, color:'#94a3b8' }}>
          Click a card to configure · drag to reorder
        </div>
      </div>

      <div style={{ display:'grid',
                    gridTemplateColumns:'repeat(auto-fill, minmax(180px, 1fr))',
                    gap:12 }}>
        {local.map((t, idx) => {
          const hidden     = t.show === false;
          const sel        = selectedOid === t._oid;
          const isDragging = dragIdx === idx;
          const isOver     = overIdx === idx && dragIdx !== idx;
          return (
            <div key={t._oid}
              draggable
              onDragStart={() => onDragStart(idx)}
              onDragEnter={() => onDragEnter(idx)}
              onDragEnd={onDragEnd}
              onDragOver={e => e.preventDefault()}
              onClick={() => onSelectTable && onSelectTable(t)}
              style={{
                background:   hidden ? '#f8fafc' : '#fff',
                border:       sel    ? '2px solid #2563eb'
                            : isOver ? '2px dashed #93c5fd'
                                     : '1.5px solid #e2e8f0',
                borderRadius: 10,
                padding:      '16px 14px',
                cursor:       'pointer',
                opacity:      isDragging ? 0.4 : hidden ? 0.55 : 1,
                position:     'relative',
                minHeight:    100,
                transition:   'border-color 0.12s, opacity 0.12s',
                userSelect:   'none',
              }}>

              <div style={{ position:'absolute', top:8, left:8,
                            fontSize:10, color:'#cbd5e1', fontWeight:700 }}>
                #{idx + 1}
              </div>

              {hidden && (
                <div style={{ position:'absolute', top:8, right:8, fontSize:9,
                              background:'#f1f5f9', color:'#94a3b8',
                              padding:'1px 6px', borderRadius:4,
                              fontWeight:600, textTransform:'uppercase' }}>
                  hidden
                </div>
              )}

              <div style={{ fontSize:28, marginBottom:8, marginTop:4 }}>
                {t.icon || '📄'}
              </div>
              <div style={{ fontSize:14, fontWeight:700, color:'#0f1923',
                            marginBottom:4, lineHeight:1.2 }}>
                {t.name}
              </div>
              <div style={{ fontSize:12, color:'#64748b', lineHeight:1.5,
                            overflow:'hidden', display:'-webkit-box',
                            WebkitLineClamp:2, WebkitBoxOrient:'vertical' }}>
                {t.desc || ''}
              </div>
              <div style={{ marginTop:8, fontSize:10,
                            color: t.link==='detail' ? '#7c3aed' : '#2563eb',
                            background: t.link==='detail' ? '#faf5ff' : '#eff6ff',
                            display:'inline-block', padding:'2px 7px',
                            borderRadius:4, fontWeight:600 }}>
                → {t.link === 'detail' ? 'Detail' : 'List'}
              </div>
            </div>
          );
        })}
      </div>

      <div style={{ marginTop:16, fontSize:11, color:'#94a3b8', background:'#f8fafc',
                    borderRadius:6, padding:'8px 12px', border:'1px solid #f1f5f9' }}>
        📱 On mobile: cards display full width, one per row · 🖥 Desktop: 4 per row
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────
// HomeInspector — inspector for Home Page cards
// ─────────────────────────────────────────────
function HomeInspector({ table, onUpdate }) {
  const [local, setLocal] = React.useState(null);

  React.useEffect(() => {
    setLocal(table ? { ...table } : null);
  }, [table?._oid]);

  if (!local) return (
    <div style={{ padding:14 }}>
      <div style={{ display:'flex', alignItems:'center', gap:6, marginBottom:12,
                    paddingBottom:8, borderBottom:'1px solid #f1f5f9' }}>
        <span style={SDS.inspHeader}>Inspector</span>
        {typeof KBIcon !== 'undefined' && <KBIcon kbKey="design.home.inspector" />}
      </div>
      <div style={{ fontSize:12, color:'#94a3b8', textAlign:'center', marginTop:40 }}>
        Click a card<br/>to configure
      </div>
    </div>
  );

  function set(key, val) {
    const updated = { ...local, [key]: val };
    setLocal(updated);
    onUpdate && onUpdate(updated);
  }

  const lbl = txt => <div style={SDS.inspLabel}>{txt}</div>;

  return (
    <div style={SDS.inspPanel}>
      <div style={SDS.inspHeaderRow}>
        <span style={SDS.inspHeader}>Inspector</span>
        <div style={{ display:'flex', alignItems:'center', gap:4 }}>
          {typeof KBIcon !== 'undefined' && <KBIcon kbKey="design.home.inspector" />}
          <span style={SDS.inspBadge('#059669')}>Table</span>
        </div>
      </div>

      {lbl('Table Name')}
      <input value={local.name || ''} onChange={e => set('name', e.target.value)}
        style={SDS.inspInput} placeholder="Display name" />

      {lbl('Description')}
      <textarea value={local.desc || ''} onChange={e => set('desc', e.target.value)}
        style={{ ...SDS.inspInput, height:64, resize:'vertical' }}
        maxLength={120} placeholder="Short description" />
      <div style={{ fontSize:10, color:'#94a3b8', marginBottom:8, textAlign:'right' }}>
        {(local.desc||'').length}/120
      </div>

      {lbl('Icon (Emoji)')}
      <input value={local.icon || ''} onChange={e => set('icon', e.target.value)}
        style={{ ...SDS.inspInput, fontSize:20, textAlign:'center', width:56 }}
        maxLength={4} />

      {lbl('Show on Home')}
      <div style={{ display:'flex', border:'1.5px solid #e2e8f0', borderRadius:6,
                    overflow:'hidden', marginBottom:8 }}>
        {[['Visible', true], ['Hidden', false]].map(([l, v]) => {
          const active = v === true ? local.show !== false : local.show === false;
          return (
            <button key={l} type="button" onClick={() => set('show', v)}
              style={{ flex:1, padding:'6px 4px', border:'none', fontSize:12,
                       fontWeight:500, cursor:'pointer', fontFamily:'DM Sans, sans-serif',
                       background: active ? '#0f1923' : '#fff',
                       color:      active ? '#fff'    : '#64748b' }}>
              {l}
            </button>
          );
        })}
      </div>

      {lbl('Opens To')}
      <div style={{ display:'flex', border:'1.5px solid #e2e8f0', borderRadius:6,
                    overflow:'hidden' }}>
        {[['list','List View'],['detail','Detail View']].map(([v,l]) => (
          <button key={v} type="button" onClick={() => set('link', v)}
            style={{ flex:1, padding:'6px 4px', border:'none', fontSize:12,
                     fontWeight:500, cursor:'pointer', fontFamily:'DM Sans, sans-serif',
                     background: (local.link||'list') === v ? '#0f1923' : '#fff',
                     color:      (local.link||'list') === v ? '#fff'    : '#64748b' }}>
            {l}
          </button>
        ))}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────
// ColDropZone — renders one col with its objects
// ─────────────────────────────────────────────
