// GHL form connection settings — owner-only (Justin).
const { useState: useStateConn, useMemo: useMemoConn } = React;

const HUB_FIELDS = {
  saf: [
    { id: 'teamId', label: 'Club / team', required: true },
    { id: 'officer.name', label: 'Officer name', required: true },
    { id: 'officer.position', label: 'Officer position', required: true },
    { id: 'officer.email', label: 'Officer email', required: true },
    { id: 'date', label: 'Date of purchase', required: true },
    { id: 'isReimbursement', label: 'Is reimbursement?', required: true },
    { id: 'category', label: 'Event category', required: true },
    { id: 'vendor.name', label: 'Vendor name', required: true },
    { id: 'vendor.phone', label: 'Vendor phone' },
    { id: 'vendor.address', label: 'Vendor address', required: true },
    { id: 'vendor.email', label: 'Vendor email' },
    { id: 'amount', label: 'Amount', required: true },
    { id: 'justification', label: 'Justification', required: true },
    { id: 'receipt', label: 'Receipt file', required: true },
    { id: 'gas.cars', label: 'Gas: cars taken' },
    { id: 'gas.from', label: 'Gas: departure address' },
    { id: 'gas.to', label: 'Gas: destination address' },
  ],
  incident: [
    { id: 'teamId', label: 'Club / team', required: true },
    { id: 'reporter', label: 'Reporter name', required: true },
    { id: 'date', label: 'Incident date', required: true },
    { id: 'severity', label: 'Severity', required: true },
    { id: 'description', label: 'Description', required: true },
    { id: 'injured', label: 'Injured person' },
  ],
  travel: [
    { id: 'teamId', label: 'Club / team', required: true },
    { id: 'eventName', label: 'Event name', required: true },
    { id: 'date', label: 'Date', required: true },
    { id: 'location', label: 'Location', required: true },
    { id: 'transportation', label: 'Transportation' },
    { id: 'driverList', label: 'Approved drivers' },
  ],
  officer: [
    { id: 'teamId', label: 'Club / team', required: true },
    { id: 'name', label: 'Officer name', required: true },
    { id: 'position', label: 'E-board position', required: true },
    { id: 'email', label: 'Email', required: true },
    { id: 'term', label: 'Term year', required: true },
  ],
};

const HUB_FORM_TYPES = [
  { id: 'saf', label: 'SAF purchasing application', icon: 'Dollar' },
  { id: 'incident', label: 'Incident / injury report', icon: 'AlertTriangle' },
  { id: 'travel', label: 'Travel itinerary', icon: 'MapPin' },
  { id: 'officer', label: 'Officer registration', icon: 'User' },
];

const SEED_CONNECTIONS = [
  {
    id: 'conn-saf',
    ghlFormName: 'Club Sports SAF Purchasing Application',
    ghlFormId: 'gh_form_8f3c2',
    hubType: 'saf',
    status: 'live',
    lastDelivery: '2026-05-22T08:14:00',
    lastDeliverySaf: 'Ewigleben Ice Arena · $1,240',
    received24h: 3,
    failed24h: 0,
    webhookUrl: 'https://recsports-hub.ferris.edu/api/ghl/saf',
    secret: 'whsec_rsh_saf_••••••••••••',
    mapped: 14,
    total: 17,
  },
  {
    id: 'conn-incident',
    ghlFormName: 'Club Sports Incident Report',
    ghlFormId: 'gh_form_2a1b9',
    hubType: 'incident',
    status: 'live',
    lastDelivery: '2026-05-19T14:42:00',
    lastDeliverySaf: 'Sprained ankle · Men\'s Lacrosse',
    received24h: 0,
    failed24h: 0,
    webhookUrl: 'https://recsports-hub.ferris.edu/api/ghl/incident',
    secret: 'whsec_rsh_inc_••••••••••••',
    mapped: 6,
    total: 6,
  },
  {
    id: 'conn-travel',
    ghlFormName: 'Away Game Travel Itinerary',
    ghlFormId: 'gh_form_5e7d4',
    hubType: 'travel',
    status: 'needs-mapping',
    lastDelivery: '2026-05-18T11:02:00',
    lastDeliverySaf: '2 fields not mapped',
    received24h: 1,
    failed24h: 1,
    webhookUrl: 'https://recsports-hub.ferris.edu/api/ghl/travel',
    secret: 'whsec_rsh_trv_••••••••••••',
    mapped: 4,
    total: 6,
  },
  {
    id: 'conn-officer',
    ghlFormName: 'Officer Registration 2026–27',
    ghlFormId: 'gh_form_9c4a1',
    hubType: 'officer',
    status: 'paused',
    lastDelivery: null,
    lastDeliverySaf: null,
    received24h: 0,
    failed24h: 0,
    webhookUrl: 'https://recsports-hub.ferris.edu/api/ghl/officer',
    secret: 'whsec_rsh_off_••••••••••••',
    mapped: 5,
    total: 5,
  },
];

const SAMPLE_GHL_FIELDS = {
  saf: [
    { id: 'g_clubname', label: 'FSU Club Name' },
    { id: 'g_officer', label: 'Officer completing form' },
    { id: 'g_position', label: 'Officer Position on E-board' },
    { id: 'g_officeremail', label: 'Officer Email' },
    { id: 'g_date', label: 'Date' },
    { id: 'g_reimburse', label: 'Is this a Reimbursement' },
    { id: 'g_category', label: 'Event category' },
    { id: 'g_other', label: 'Other Expenses' },
    { id: 'g_vname', label: 'Vendor Full Name' },
    { id: 'g_vphone', label: 'Vendor Phone' },
    { id: 'g_vaddress', label: 'Vendor Address' },
    { id: 'g_vemail', label: 'Vendor Email' },
    { id: 'g_amt', label: 'Amount' },
    { id: 'g_justify', label: 'Justification for expenditure' },
    { id: 'g_receipt', label: 'Receipt from purchase' },
    { id: 'g_gascars', label: 'How many cars were taken' },
    { id: 'g_gasfrom', label: 'Address from departure' },
    { id: 'g_gasto', label: 'Address of destination' },
  ],
  incident: [
    { id: 'g_iclub', label: 'Club' },
    { id: 'g_ireporter', label: 'Reporter Name' },
    { id: 'g_idate', label: 'Date of incident' },
    { id: 'g_isev', label: 'Severity' },
    { id: 'g_idesc', label: 'Description' },
    { id: 'g_iinjured', label: 'Injured person' },
  ],
  travel: [
    { id: 'g_tclub', label: 'Club' },
    { id: 'g_tname', label: 'Event Name' },
    { id: 'g_tdate', label: 'Date' },
    { id: 'g_tloc', label: 'Location' },
  ],
  officer: [
    { id: 'g_oclub', label: 'Club' },
    { id: 'g_oname', label: 'Officer Name' },
    { id: 'g_opos', label: 'E-board Position' },
    { id: 'g_omail', label: 'Email' },
    { id: 'g_oterm', label: 'Term year' },
  ],
};

// Default mapping: best-match SAF (all fields) and partial for travel
const SEED_MAPPINGS = {
  'conn-saf': {
    'g_clubname': 'teamId',
    'g_officer': 'officer.name',
    'g_position': 'officer.position',
    'g_officeremail': 'officer.email',
    'g_date': 'date',
    'g_reimburse': 'isReimbursement',
    'g_category': 'category',
    'g_vname': 'vendor.name',
    'g_vphone': 'vendor.phone',
    'g_vaddress': 'vendor.address',
    'g_vemail': 'vendor.email',
    'g_amt': 'amount',
    'g_justify': 'justification',
    'g_receipt': 'receipt',
  },
  'conn-incident': {
    'g_iclub': 'teamId',
    'g_ireporter': 'reporter',
    'g_idate': 'date',
    'g_isev': 'severity',
    'g_idesc': 'description',
    'g_iinjured': 'injured',
  },
  'conn-travel': {
    'g_tclub': 'teamId',
    'g_tname': 'eventName',
    'g_tdate': 'date',
    'g_tloc': 'location',
  },
  'conn-officer': {
    'g_oclub': 'teamId',
    'g_oname': 'name',
    'g_opos': 'position',
    'g_omail': 'email',
    'g_oterm': 'term',
  },
};

function FormConnectionsScreen({ user, onBack }) {
  const [connections, setConnections] = useStateConn(SEED_CONNECTIONS);
  const [mappings, setMappings] = useStateConn(SEED_MAPPINGS);
  const [selectedId, setSelectedId] = useStateConn('conn-saf');
  const [ghlConnected, setGhlConnected] = useStateConn(true);
  const [showCopied, setShowCopied] = useStateConn(null);

  const selected = connections.find(c => c.id === selectedId);

  if (user.id !== 'u1') {
    return (
      <div className="empty" style={{ marginTop: 60 }}>
        <div className="empty-icon"><window.I.ShieldCheck size={20} /></div>
        <div className="empty-title">Owner-only area</div>
        <div className="empty-msg">Form connections are managed by the portal owner (Justin) only.</div>
      </div>
    );
  }

  function copy(text, key) {
    navigator.clipboard?.writeText(text);
    setShowCopied(key);
    setTimeout(() => setShowCopied(null), 1500);
  }

  function toggleStatus(id) {
    setConnections(cs => cs.map(c => c.id === id ? { ...c, status: c.status === 'paused' ? 'live' : 'paused' } : c));
  }

  function setMap(connId, ghlFieldId, hubFieldId) {
    setMappings(m => {
      const next = { ...(m[connId] || {}) };
      // Remove any other GHL field pointing at this hubFieldId (one-to-one)
      Object.keys(next).forEach(k => { if (next[k] === hubFieldId) delete next[k]; });
      if (hubFieldId) next[ghlFieldId] = hubFieldId;
      else delete next[ghlFieldId];
      return { ...m, [connId]: next };
    });
  }

  return (
    <div data-screen-label="10 Form connections">
      <button className="back-link" onClick={onBack}>
        <window.I.ArrowLeft size={13} /> Back
      </button>
      <div className="page-head">
        <div>
          <h1 className="page-title">
            Form connections
            <span className="badge gold" style={{ fontSize: 10 }}>OWNER ONLY</span>
          </h1>
          <div className="page-subtitle">
            GoHighLevel forms wired into RecSports Hub · only {user.name} can change these
          </div>
        </div>
        <div className="flex-gap-8">
          <button className="btn btn-secondary btn-sm">
            <window.I.Download size={13} /> Export delivery log
          </button>
          <button className="btn btn-primary btn-sm">
            <window.I.Plus size={13} /> Connect new form
          </button>
        </div>
      </div>

      <div className="card card-pad mb-16">
        <div className="flex-between">
          <div className="flex-gap-12">
            <span className="task-icon gold" style={{ width: 36, height: 36 }}>
              <window.I.RefreshCw size={18} />
            </span>
            <div>
              <div style={{ fontWeight: 600 }}>GoHighLevel account</div>
              <div className="dim" style={{ fontSize: 12 }}>
                {ghlConnected
                  ? 'Connected · Ferris Recreation (location ghl_loc_4f2a1) · OAuth token valid'
                  : 'Not connected'}
              </div>
            </div>
          </div>
          <div className="flex-gap-8">
            {ghlConnected ? (
              <>
                <span className="badge success dot">Connected</span>
                <button className="btn btn-ghost btn-sm">Reauthorize</button>
                <button className="btn btn-ghost btn-sm" onClick={() => setGhlConnected(false)}>Disconnect</button>
              </>
            ) : (
              <button className="btn btn-primary btn-sm" onClick={() => setGhlConnected(true)}>
                <window.I.ShieldCheck size={13} /> Connect GoHighLevel
              </button>
            )}
          </div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '320px 1fr', gap: 16 }}>
        {/* Left: connection list */}
        <div className="card" style={{ height: 'fit-content', position: 'sticky', top: 76 }}>
          <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--border)' }}>
            <strong style={{ fontSize: 13 }}>Connected forms</strong>
            <span className="dim" style={{ fontSize: 11, marginLeft: 6 }}>{connections.length}</span>
          </div>
          {connections.map(c => {
            const typ = HUB_FORM_TYPES.find(t => t.id === c.hubType);
            const Ic = window.I[typ?.icon] || window.I.FileText;
            const isActive = selectedId === c.id;
            const stMap = {
              live: { label: 'Live', kind: 'success' },
              paused: { label: 'Paused', kind: 'neutral' },
              'needs-mapping': { label: 'Needs mapping', kind: 'warning' },
              error: { label: 'Error', kind: 'danger' },
            };
            const st = stMap[c.status];
            return (
              <button
                key={c.id}
                onClick={() => setSelectedId(c.id)}
                style={{
                  width: '100%',
                  padding: '12px 16px',
                  textAlign: 'left',
                  background: isActive ? 'var(--surface-2)' : 'transparent',
                  borderLeft: isActive ? '2px solid var(--gold)' : '2px solid transparent',
                  borderBottom: '1px solid var(--border)',
                }}
              >
                <div className="flex-gap-8" style={{ marginBottom: 4 }}>
                  <Ic size={14} style={{ color: 'var(--text-2)' }} />
                  <strong style={{ fontSize: 13, color: 'var(--text)', flex: 1 }}>{typ?.label}</strong>
                  <span className={`badge ${st.kind} dot`} style={{ fontSize: 9 }}>{st.label}</span>
                </div>
                <div className="dim" style={{ fontSize: 11, marginLeft: 22 }}>{c.ghlFormName}</div>
                <div className="dim" style={{ fontSize: 10, marginLeft: 22, marginTop: 4 }}>
                  {c.mapped}/{c.total} fields mapped · {c.received24h} hits 24h
                </div>
              </button>
            );
          })}
        </div>

        {/* Right: detail */}
        {selected && (
          <div className="flex-col" style={{ gap: 16 }}>
            <ConnectionHeader
              conn={selected}
              copy={copy}
              showCopied={showCopied}
              onToggle={() => toggleStatus(selected.id)}
            />
            <FieldMapping
              conn={selected}
              mapping={mappings[selected.id] || {}}
              onMap={(g, h) => setMap(selected.id, g, h)}
            />
            <DeliveryLog conn={selected} />
          </div>
        )}
      </div>
    </div>
  );
}

function ConnectionHeader({ conn, copy, showCopied, onToggle }) {
  const typ = HUB_FORM_TYPES.find(t => t.id === conn.hubType);
  const Ic = window.I[typ?.icon] || window.I.FileText;
  return (
    <div className="card card-pad">
      <div className="flex-between mb-12">
        <div className="flex-gap-12">
          <span className="task-icon gold" style={{ width: 36, height: 36 }}>
            <Ic size={18} />
          </span>
          <div>
            <div style={{ fontWeight: 600, fontSize: 15 }}>{conn.ghlFormName}</div>
            <div className="dim" style={{ fontSize: 12 }}>
              GHL form ID · <code style={{ color: 'var(--text-2)' }}>{conn.ghlFormId}</code>
              &nbsp;·&nbsp; Routes to <strong style={{ color: 'var(--text)' }}>{typ?.label}</strong>
            </div>
          </div>
        </div>
        <div className="flex-gap-8">
          <button className="btn btn-secondary btn-sm">
            <window.I.Send size={13} /> Send test event
          </button>
          <button
            className={`btn btn-sm ${conn.status === 'paused' ? 'btn-primary' : 'btn-ghost'}`}
            onClick={onToggle}
          >
            {conn.status === 'paused' ? 'Resume' : 'Pause'}
          </button>
        </div>
      </div>

      <div className="form-grid cols-2" style={{ gap: 12 }}>
        <div>
          <label className="field-label">Webhook URL</label>
          <div className="flex-gap-8">
            <input className="input cell-mono" readOnly value={conn.webhookUrl} style={{ fontSize: 11 }} />
            <button className="btn btn-secondary btn-sm" onClick={() => copy(conn.webhookUrl, conn.id + '-url')}>
              {showCopied === conn.id + '-url' ? <><window.I.Check size={12} /> Copied</> : 'Copy'}
            </button>
          </div>
          <div className="dim" style={{ fontSize: 11, marginTop: 4 }}>
            Paste this into the GHL workflow webhook action.
          </div>
        </div>
        <div>
          <label className="field-label">Signing secret</label>
          <div className="flex-gap-8">
            <input className="input cell-mono" readOnly value={conn.secret} style={{ fontSize: 11 }} />
            <button className="btn btn-secondary btn-sm" onClick={() => copy(conn.secret, conn.id + '-sec')}>
              {showCopied === conn.id + '-sec' ? <><window.I.Check size={12} /> Copied</> : 'Reveal'}
            </button>
          </div>
          <div className="dim" style={{ fontSize: 11, marginTop: 4 }}>
            Verifies the request came from GHL. Rotate yearly.
          </div>
        </div>
      </div>
    </div>
  );
}

function FieldMapping({ conn, mapping, onMap }) {
  const ghlFields = SAMPLE_GHL_FIELDS[conn.hubType] || [];
  const hubFields = HUB_FIELDS[conn.hubType] || [];
  const mappedCount = Object.keys(mapping).length;
  const requiredHub = hubFields.filter(f => f.required);
  const unmappedRequired = requiredHub.filter(rf => !Object.values(mapping).includes(rf.id));

  return (
    <div className="card">
      <div className="flex-between" style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)' }}>
        <div>
          <strong style={{ fontSize: 13 }}>Field mapping</strong>
          <span className="dim" style={{ fontSize: 12, marginLeft: 8 }}>
            {mappedCount} of {ghlFields.length} GHL fields mapped
          </span>
        </div>
        <div className="flex-gap-8">
          {unmappedRequired.length > 0 && (
            <span className="badge danger">{unmappedRequired.length} required missing</span>
          )}
          <button className="btn btn-ghost btn-sm">
            <window.I.RefreshCw size={12} /> Auto-map by label
          </button>
        </div>
      </div>

      <div style={{ padding: 16 }}>
        <div style={{
          display: 'grid',
          gridTemplateColumns: '1fr 24px 1fr',
          gap: '8px 12px',
          alignItems: 'center',
        }}>
          <div className="section-title" style={{ margin: 0 }}>GHL form field</div>
          <div></div>
          <div className="section-title" style={{ margin: 0 }}>Hub field</div>

          {ghlFields.map(gf => {
            const mappedTo = mapping[gf.id];
            const hubField = hubFields.find(h => h.id === mappedTo);
            return (
              <React.Fragment key={gf.id}>
                <div style={{
                  padding: '8px 12px',
                  background: 'var(--surface-2)',
                  border: '1px solid var(--border)',
                  borderRadius: 6,
                  fontSize: 12,
                }}>
                  <div style={{ fontWeight: 600 }}>{gf.label}</div>
                  <div className="dim cell-mono" style={{ fontSize: 10 }}>{gf.id}</div>
                </div>
                <div style={{ textAlign: 'center', color: 'var(--text-3)', fontSize: 14 }}>→</div>
                <select
                  className="select"
                  value={mappedTo || ''}
                  onChange={e => onMap(gf.id, e.target.value)}
                  style={{
                    fontSize: 12,
                    background: !mappedTo ? 'var(--bg)' : (hubField?.required ? 'rgba(76,175,80,0.04)' : 'var(--surface)'),
                  }}
                >
                  <option value="">— skip this field —</option>
                  {hubFields.map(hf => (
                    <option key={hf.id} value={hf.id}>
                      {hf.label}{hf.required ? ' *' : ''}
                    </option>
                  ))}
                </select>
              </React.Fragment>
            );
          })}
        </div>

        {unmappedRequired.length > 0 && (
          <div className="tip mt-16" style={{ borderLeftColor: 'var(--danger)', background: 'rgba(229,57,53,0.05)' }}>
            <window.I.AlertTriangle size={14} style={{ flexShrink: 0, color: 'var(--danger)' }} />
            <div style={{ fontSize: 12 }}>
              <strong style={{ color: 'var(--danger)' }}>Required Hub fields without a source:</strong>{' '}
              {unmappedRequired.map(f => f.label).join(', ')}.{' '}
              Either map a GHL field to each, or add a default value below.
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

function DeliveryLog({ conn }) {
  // Synthesize a fake delivery log
  const rows = useMemoConn(() => {
    const base = conn.lastDelivery ? new Date(conn.lastDelivery) : new Date('2026-05-22T10:00:00');
    const out = [];
    for (let i = 0; i < 6; i++) {
      const t = new Date(base);
      t.setHours(t.getHours() - i * 5 - i * 2);
      const isFail = conn.failed24h > 0 && i === 2;
      out.push({
        id: 'd' + i,
        at: t.toISOString(),
        result: isFail ? 'fail' : 'ok',
        latencyMs: 320 + (i * 73 + conn.id.length * 11) % 400,
        message: isFail
          ? 'Missing required field: "FSU Club Name"'
          : (i === 0 ? conn.lastDeliverySaf : 'Created record in Hub'),
        ghlSub: 'sub_' + (1000 + i * 17),
      });
    }
    return out;
  }, [conn]);

  const Fmt = window.Fmt;

  return (
    <div className="card">
      <div className="flex-between" style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)' }}>
        <div>
          <strong style={{ fontSize: 13 }}>Recent deliveries</strong>
          <span className="dim" style={{ fontSize: 12, marginLeft: 8 }}>
            Last 24h: {conn.received24h} received · {conn.failed24h} failed
          </span>
        </div>
        <button className="btn btn-ghost btn-sm">
          <window.I.Download size={12} /> Export log
        </button>
      </div>
      <div className="table-wrap">
        <table className="data">
          <thead>
            <tr>
              <th>Received</th>
              <th>GHL submission</th>
              <th>Latency</th>
              <th>Result</th>
              <th>Message</th>
              <th style={{ textAlign: 'right' }}></th>
            </tr>
          </thead>
          <tbody>
            {rows.length === 0 ? (
              <tr><td colSpan={6}>
                <div className="empty" style={{ padding: '32px 20px' }}>
                  <div className="empty-title">No deliveries yet</div>
                  <div className="empty-msg">Submit the form in GHL to see events here.</div>
                </div>
              </td></tr>
            ) : rows.map(r => (
              <tr key={r.id}>
                <td className="cell-muted cell-mono">{Fmt.dateTime(r.at)}</td>
                <td className="cell-mono cell-muted">{r.ghlSub}</td>
                <td className="cell-mono cell-muted">{r.latencyMs} ms</td>
                <td>
                  {r.result === 'ok'
                    ? <span className="badge success dot">200 OK</span>
                    : <span className="badge danger dot">400 fail</span>}
                </td>
                <td className="cell-muted" style={{ fontSize: 12 }}>{r.message}</td>
                <td style={{ textAlign: 'right' }}>
                  <button className="btn btn-ghost btn-xs">
                    {r.result === 'ok' ? 'View payload' : 'Retry'}
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

window.FormConnectionsScreen = FormConnectionsScreen;
