// ─────────────────────────────────────────────
// DO_DetailView_Portal.jsx
// Portal runtime component for the APP detail view
//
// Loaded in: do-app/index.html (before DO_DetailView.jsx)
// Used by:   RenderObject in DO_DetailView.jsx as:
//   case "portal": return <PortalField obj={obj} appId={appId} recordId={recordId} appData={appData} />;
//
// Portal fetches related records via o_joins:
//   GET /v6/portal?app=X&parentTable=t1&parentRecord=42&relatedTable=t2
//
// Portal add creates record + join:
//   POST /v6/portal/add { app, parentTable, parentRecord, relatedTable, fields }
//
// Portal delete soft-deletes join entry:
//   DELETE /v6/portal/delete?app=X&parentTable=t1&parentRecord=42&relatedTable=t2&relatedRecord=Y
//
// Portal object JSON (from objects table):
//   relatedTable   — 't2'
//   displayFields  — ['1','2','3']  (o_field numbers without 'f')
//   sortField      — '1'
//   sortDir        — 'desc' | 'asc'
//   allowAdd       — 'yes' | 'no'
//   allowDelete    — 'yes' | 'no'
//   quickAddMode   — 'single' | 'all' | 'none'
//   quickAddField  — '1'  (for single mode)
//   portalRows     — 10
//   label          — 'Notes'
// ─────────────────────────────────────────────

function PortalField({ obj, appId, table: parentTable, recordId, appData }) {

  const [rows,      setRows]      = React.useState([]);
  const [loading,   setLoading]   = React.useState(true);
  const [error,     setError]     = React.useState(null);
  const [addOpen,   setAddOpen]   = React.useState(false);
  const [addValues, setAddValues] = React.useState({});
  const [saving,    setSaving]    = React.useState(false);
  const [deleting,  setDeleting]  = React.useState(null); // r_auto being deleted
  const [relFields, setRelFields] = React.useState([]);   // field defs for related table

  const relatedTable  = obj.relatedTable;
  const displayFields = Array.isArray(obj.displayFields) ? obj.displayFields : [];
  const sortField     = obj.sortField  || '';
  const sortDir       = obj.sortDir    || 'desc';
  const allowAdd      = obj.allowAdd   === 'yes' || obj.allowAdd   === true;
  const allowDelete   = obj.allowDelete === 'yes' || obj.allowDelete === true;
  const quickMode     = obj.quickAddMode || 'all';
  const quickField    = obj.quickAddField || '';
  const rowLimit      = parseInt(obj.portalRows) || 10;
  const label         = obj.label || 'Related Records';

  // ── Load related records ──────────────────────
  function loadPortal() {
    if (!relatedTable || !recordId) return;
    setLoading(true); setError(null);
    const url = `${API_BASE}/v6/portal?app=${appId}&parentTable=${parentTable}&parentRecord=${recordId}&relatedTable=${relatedTable}&sortField=${sortField}&sortDir=${sortDir}&limit=${rowLimit}`;
    apiFetch(url)
      .then(r => r.json())
      .then(data => {
        if (data.status !== 'ok') throw new Error(data.message);
        setRows(data.records || []);
        setRelFields(data.fields || []);
      })
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));
  }

  React.useEffect(() => { loadPortal(); }, [appId, parentTable, recordId, relatedTable]);

  // ── Field helpers ─────────────────────────────
  // Get display fields — either configured or all
  function getDisplayFields() {
    if (displayFields.length > 0) {
      return relFields.filter(f => {
        const fNum = String(f.field).replace('f','');
        return displayFields.includes(fNum) || displayFields.includes(f.field);
      });
    }
    return relFields;
  }

  function fieldKey(f) {
    // field names in returned records use 'f1','f2' format
    const n = String(f.field).replace('f','');
    return `f${n}`;
  }

  // ── Add record ────────────────────────────────
  function handleAddOpen() {
    setAddValues({});
    setAddOpen(true);
  }

  async function handleAddSave() {
    if (!relatedTable) return;
    setSaving(true);
    try {
      const res  = await apiFetch(`${API_BASE}/v6/portal/add`, {
        method: 'POST',
        body:   JSON.stringify({
          app:           appId,
          parentTable,
          parentRecord:  recordId,
          relatedTable,
          fields:        addValues,
        }),
      });
      const data = await res.json();
      if (data.status !== 'ok') throw new Error(data.message);
      setAddOpen(false);
      setAddValues({});
      loadPortal();
    } catch(e) {
      alert('Failed to add record: ' + e.message);
    }
    setSaving(false);
  }

  // ── Delete record ─────────────────────────────
  async function handleDelete(relRecord) {
    if (!confirm('Remove this related record?')) return;
    setDeleting(relRecord);
    try {
      await apiFetch(
        `${API_BASE}/v6/portal/delete?app=${appId}&parentTable=${parentTable}&parentRecord=${recordId}&relatedTable=${relatedTable}&relatedRecord=${relRecord}`,
        { method: 'DELETE' }
      );
      loadPortal();
    } catch(e) {
      alert('Delete failed: ' + e.message);
    }
    setDeleting(null);
  }

  // ── Quick add fields to show ──────────────────
  function getQuickAddFields() {
    if (quickMode === 'none') return [];
    if (quickMode === 'single' && quickField) {
      return relFields.filter(f => String(f.field).replace('f','') === String(quickField));
    }
    // 'all' or fallback
    if (displayFields.length > 0) return getDisplayFields();
    return relFields;
  }

  const visibleFields = getDisplayFields();
  const addFields     = getQuickAddFields();

  if (!relatedTable) {
    return (
      <div style={SP.wrap}>
        <div style={SP.header}>
          <span style={SP.headerLabel}>{label}</span>
        </div>
        <div style={SP.empty}>Portal not configured — set Related Table in DEV</div>
      </div>
    );
  }

  return (
    <div style={SP.wrap}>
      {/* ── Portal Header ── */}
      <div style={SP.header}>
        <span style={SP.headerLabel}>
          {label}
          {rows.length > 0 && (
            <span style={SP.count}>({rows.length})</span>
          )}
        </span>
        {allowAdd && !addOpen && (
          <button style={SP.addBtn} onClick={handleAddOpen}>+ Add</button>
        )}
      </div>

      {/* ── Error ── */}
      {error && (
        <div style={SP.error}>{error}</div>
      )}

      {/* ── Loading ── */}
      {loading && (
        <div style={SP.loading}>
          {[1,2,3].map(i => (
            <div key={i} style={SP.skeleton} />
          ))}
        </div>
      )}

      {/* ── Quick Add Row ── */}
      {addOpen && (
        <div style={SP.addRow}>
          {addFields.map(f => {
            const fk = fieldKey(f);
            return (
              <div key={fk} style={{ flex: quickMode === 'single' ? 3 : 1, minWidth:80 }}>
                {quickMode !== 'single' && (
                  <div style={SP.addFieldLabel}>{f.name}</div>
                )}
                <input
                  style={SP.addInput}
                  placeholder={f.name}
                  value={addValues[fk] || ''}
                  onChange={e => setAddValues(prev => ({ ...prev, [fk]: e.target.value }))}
                  autoFocus={addFields[0] === f}
                  onKeyDown={e => {
                    if (e.key === 'Enter' && quickMode === 'single') handleAddSave();
                    if (e.key === 'Escape') { setAddOpen(false); setAddValues({}); }
                  }}
                />
              </div>
            );
          })}
          <div style={{ display:'flex', gap:4, flexShrink:0 }}>
            <button style={SP.saveBtn} onClick={handleAddSave} disabled={saving}>
              {saving ? '…' : '✓'}
            </button>
            <button style={SP.cancelBtn} onClick={() => { setAddOpen(false); setAddValues({}); }}>
              ✕
            </button>
          </div>
        </div>
      )}

      {/* ── Records ── */}
      {!loading && rows.length === 0 && !addOpen && (
        <div style={SP.empty}>
          No {label.toLowerCase()} yet
          {allowAdd && <span style={{ color:'#2563eb', cursor:'pointer', marginLeft:6 }}
            onClick={handleAddOpen}>— add one</span>}
        </div>
      )}

      {!loading && rows.length > 0 && (
        <div>
          {/* Column headers — show if multiple display fields */}
          {visibleFields.length > 1 && (
            <div style={SP.colHeader}>
              {visibleFields.map(f => (
                <div key={f.field} style={{ flex:1, overflow:'hidden' }}>{f.name}</div>
              ))}
              {allowDelete && <div style={{ width:24 }} />}
            </div>
          )}

          {/* Data rows */}
          {rows.map(row => (
            <div key={row.r_auto} style={{
              ...SP.dataRow,
              opacity: deleting === row.r_auto ? 0.4 : 1,
            }}>
              {visibleFields.length > 0
                ? visibleFields.map(f => (
                    <div key={f.field} style={SP.dataCell}>
                      {row[fieldKey(f)] || <span style={{ color:'#cbd5e1' }}>—</span>}
                    </div>
                  ))
                : <div style={{ ...SP.dataCell, flex:3, color:'#64748b', fontSize:12 }}>
                    Record #{row.r_auto}
                  </div>
              }
              {allowDelete && (
                <button
                  style={SP.deleteBtn}
                  onClick={() => handleDelete(row.r_auto)}
                  disabled={deleting === row.r_auto}
                  title="Remove">
                  ✕
                </button>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Portal styles ────────────────────────────
const SP = {
  wrap:          { border:'1px solid #e2e8f0', borderRadius:8, overflow:'hidden',
                   marginBottom:12, background:'#fff' },
  header:        { display:'flex', alignItems:'center', justifyContent:'space-between',
                   background:'#1a3566', padding:'7px 12px' },
  headerLabel:   { fontSize:12, fontWeight:700, color:'#fff', display:'flex',
                   alignItems:'center', gap:6 },
  count:         { fontSize:11, color:'rgba(255,255,255,0.6)', fontWeight:400 },
  addBtn:        { fontSize:11, fontWeight:600, color:'#fff', background:'rgba(255,255,255,0.15)',
                   border:'1px solid rgba(255,255,255,0.25)', borderRadius:4, padding:'2px 10px',
                   cursor:'pointer', fontFamily:'inherit' },
  error:         { background:'#fef2f2', color:'#dc2626', padding:'8px 12px',
                   fontSize:12, borderBottom:'1px solid #fecdd3' },
  loading:       { padding:'8px 12px', display:'flex', flexDirection:'column', gap:6 },
  skeleton:      { height:20, background:'#f1f5f9', borderRadius:4,
                   animation:'pulse 1.5s ease-in-out infinite' },
  empty:         { padding:'14px 12px', fontSize:12, color:'#94a3b8', textAlign:'center' },
  colHeader:     { display:'flex', alignItems:'center', padding:'5px 12px',
                   background:'#f8fafc', borderBottom:'1px solid #f1f5f9',
                   fontSize:10, fontWeight:700, color:'#64748b',
                   textTransform:'uppercase', letterSpacing:'0.05em', gap:8 },
  dataRow:       { display:'flex', alignItems:'center', padding:'7px 12px',
                   borderBottom:'1px solid #f8fafc', gap:8, transition:'opacity 0.2s' },
  dataCell:      { flex:1, fontSize:13, color:'#374151', overflow:'hidden',
                   textOverflow:'ellipsis', whiteSpace:'nowrap' },
  deleteBtn:     { background:'none', border:'none', color:'#fca5a5', cursor:'pointer',
                   fontSize:12, padding:'0 2px', fontFamily:'inherit', width:24,
                   flexShrink:0 },
  addRow:        { display:'flex', alignItems:'flex-end', gap:6, padding:'8px 10px',
                   background:'#fffbf0', borderBottom:'1px solid #fde68a' },
  addFieldLabel: { fontSize:10, fontWeight:600, color:'#92400e', marginBottom:3,
                   textTransform:'uppercase', letterSpacing:'0.05em' },
  addInput:      { width:'100%', padding:'6px 8px', border:'1.5px solid #fde68a',
                   borderRadius:6, fontSize:13, fontFamily:'DM Sans, sans-serif',
                   outline:'none', background:'#fff', color:'#0f1923' },
  saveBtn:       { padding:'6px 10px', background:'#16a34a', color:'#fff', border:'none',
                   borderRadius:6, fontSize:13, cursor:'pointer', fontFamily:'inherit',
                   fontWeight:700 },
  cancelBtn:     { padding:'6px 8px', background:'#fff', color:'#64748b',
                   border:'1.5px solid #e2e8f0', borderRadius:6, fontSize:12,
                   cursor:'pointer', fontFamily:'inherit' },
};
