/* ============================================================
   UNSTOPPABLES — Client Dossier (record detail)
   Section rail · completeness ring · masked PII w/ reveal ·
   inline fill-the-gap editing · visit timeline
   Exports: ClientDossier, CompletenessRing, StaffAvatar
   ============================================================ */

function CompletenessRing({ pct, size = 52, label = true }) {
  const r = (size - 8) / 2, c = 2 * Math.PI * r;
  const tone = pct >= 80 ? 'var(--leaf)' : pct >= 50 ? 'var(--gold-deep)' : 'var(--coral)';
  return (
    <div style={{ position: 'relative', width: size, height: size, flexShrink: 0 }} title={`Record completeness ${pct}%`}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="var(--hover)" strokeWidth="4"></circle>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke={tone} strokeWidth="4" strokeLinecap="round"
          strokeDasharray={c} strokeDashoffset={c * (1 - pct / 100)} style={{ transition: 'stroke-dashoffset .6s var(--ease-spring)' }}></circle>
      </svg>
      {label && <span className="mono" style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', fontSize: size * 0.26, fontWeight: 700 }}>{pct}</span>}
    </div>
  );
}

function StaffAvatar({ staff, size = 24 }) {
  if (!staff) return null;
  return staff.image ? (
    <img src={staff.image} alt={staff.name} style={{ width: size, height: size, borderRadius: 99, objectFit: 'cover', display: 'block', border: '1px solid var(--hairline-strong)' }} />
  ) : (
    <span style={{
      width: size, height: size, borderRadius: 99, display: 'grid', placeItems: 'center', flexShrink: 0,
      background: 'var(--accent)', color: 'var(--accent-ink)', fontSize: size * 0.38, fontWeight: 800
    }}>{staff.initials.slice(0, 2)}</span>
  );
}

/* masked value chip */
function MaskedValue({ field }) {
  const max = field.strength === 'max';
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 10px', borderRadius: 8,
      background: max ? 'var(--coral-soft)' : 'var(--hover)', border: '1px dashed var(--hairline-strong)',
      fontSize: 12.5, color: 'var(--ink-faint)', fontFamily: 'var(--font-mono)'
    }}>
      <Icon name="lock" size={11} node={false} /> {max ? '•••• ••• ••• · PHIPA' : '••••••'}
    </span>
  );
}

/* inline editor for one field (fill-the-gap) */
function FieldEditor({ field, onSave, onCancel }) {
  const [val, setVal] = React.useState(field.type === 'multi' ? [] : field.type === 'toggle' ? false : '');
  const [specify, setSpecify] = React.useState('');
  const needsSpecify = field.other && (val === 'Other' || (Array.isArray(val) && val.includes('Other')));
  const canSave = field.type === 'toggle' ? true : Array.isArray(val) ? val.length > 0 : String(val).trim() !== '';

  const chipStyle = on => ({
    padding: '7px 13px', borderRadius: 99, fontSize: 12, fontWeight: 700, minHeight: 34,
    background: on ? 'var(--accent)' : 'var(--hover)', color: on ? 'var(--accent-ink)' : 'var(--ink-soft)',
    border: '1px solid ' + (on ? 'transparent' : 'var(--hairline)'), transition: 'all .15s'
  });
  const inputStyle = {
    width: '100%', padding: '9px 12px', borderRadius: 10, border: '1px solid var(--hairline-strong)',
    background: 'var(--glass-input)', fontSize: 13.5, outline: 'none', boxSizing: 'border-box', fontFamily: 'var(--font-body)'
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8, width: '100%' }}>
      {field.type === 'text' && <input autoFocus value={val} onChange={e => setVal(e.target.value)} placeholder={field.label} style={inputStyle} />}
      {field.type === 'date' && <input type="date" value={val} onChange={e => setVal(e.target.value)} style={inputStyle} />}
      {field.type === 'select' && (field.options.length > 6 ? (
        <select value={val} onChange={e => setVal(e.target.value)} style={{ ...inputStyle, appearance: 'none' }}>
          <option value="">Choose…</option>
          {field.options.map(o => <option key={o} value={o}>{o}</option>)}
        </select>
      ) : (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {field.options.map(o => <button key={o} onClick={() => setVal(o)} style={chipStyle(val === o)}>{o}</button>)}
        </div>
      ))}
      {field.type === 'multi' && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {field.options.map(o => {
            const on = val.includes(o);
            return <button key={o} onClick={() => setVal(v => on ? v.filter(x => x !== o) : [...v, o])} style={chipStyle(on)}>{on ? '✓ ' : ''}{o}</button>;
          })}
        </div>
      )}
      {field.type === 'toggle' && (
        <div style={{ display: 'flex', gap: 6 }}>
          {[[true, 'Yes'], [false, 'No']].map(([v, l]) => <button key={l} onClick={() => setVal(v)} style={chipStyle(val === v)}>{l}</button>)}
        </div>
      )}
      {needsSpecify && <input value={specify} onChange={e => setSpecify(e.target.value)} placeholder="Please specify…" style={inputStyle} />}
      <div style={{ display: 'flex', gap: 6 }}>
        <button onClick={() => canSave && onSave(val, specify)} disabled={!canSave} title="Confirm and save" style={{
          display: 'inline-flex', alignItems: 'center', gap: 6, padding: '8px 14px', borderRadius: 10, fontSize: 12.5, fontWeight: 700,
          background: canSave ? 'var(--leaf)' : 'var(--hover)', color: canSave ? 'white' : 'var(--ink-faint)',
          cursor: canSave ? 'pointer' : 'not-allowed'
        }}><Icon name="check" size={13} stroke={2.6} node={false} /> Save</button>
        <button onClick={onCancel} style={{ padding: '8px 12px', borderRadius: 10, fontSize: 12.5, fontWeight: 700, background: 'var(--hover)' }}>Cancel</button>
      </div>
    </div>
  );
}

/* one field row in a section */
function FieldRow({ field, rec, canSee, role, onEdit, editing, setEditing, push }) {
  const S = window.TRELLIS_SCHEMA;
  const [signing, setSigning] = React.useState(false);
  const isSig = field.k === 'clientSignature';
  const v = rec[field.k];
  const has = S.filled(v);
  const isEditing = editing === field.k;
  const display = Array.isArray(v) ? v : v;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 5, padding: '11px 0', borderBottom: '1px solid var(--hairline)' }}>
      <span style={{ fontSize: 11.5, fontWeight: 700, letterSpacing: '.05em', textTransform: 'uppercase', color: 'var(--ink-faint)', display: 'flex', alignItems: 'center', gap: 6 }}>
        {field.label}{field.req && <span style={{ color: 'var(--coral)' }}>*</span>}
        {field.pii && <Icon name="lock" size={10} node={false} style={{ opacity: 0.6 }} />}
      </span>
      {isEditing ? (
        <FieldEditor field={field} onCancel={() => setEditing(null)} onSave={(val, specify) => onEdit(field, val, specify)} />
      ) : !has ? (
        field.type === 'readonly' ? <span className="t-faint" style={{ fontSize: 13.5 }}>—</span> : (
          <button onClick={() => isSig ? setSigning(true) : setEditing(field.k)} style={{
            alignSelf: 'flex-start', display: 'inline-flex', alignItems: 'center', gap: 6, padding: '6px 12px',
            borderRadius: 9, fontSize: 12.5, fontWeight: 700, color: 'var(--accent)',
            background: 'var(--accent-soft)', border: '1px dashed var(--hairline-strong)'
          }}><Icon name="plus" size={12} stroke={2.4} node={false} /> Add</button>
        )
      ) : field.pii && !canSee ? (
        <MaskedValue field={field} />
      ) : Array.isArray(display) ? (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
          {display.map(x => <span key={x} style={{ padding: '4px 11px', borderRadius: 99, fontSize: 12, fontWeight: 600, background: 'var(--hover)', border: '1px solid var(--hairline)' }}>{x}</span>)}
          {rec[field.k + 'Specify'] && <span style={{ padding: '4px 11px', borderRadius: 99, fontSize: 12, fontWeight: 600, background: 'var(--gold-soft)' }}>→ {rec[field.k + 'Specify']}</span>}
        </div>
      ) : typeof display === 'boolean' ? (
        <Badge tone={display ? 'leaf' : 'gold'}>{display ? 'Yes' : 'No'}</Badge>
      ) : typeof display === 'string' && display.startsWith('data:image') ? (
        <img src={display} alt="Client signature" onClick={() => isSig && setSigning(true)}
          title={isSig ? 'Click to re-sign' : undefined}
          style={{ height: 64, width: 'auto', maxWidth: 280, background: '#fff', borderRadius: 10,
                   border: '1px solid var(--hairline-strong)', cursor: isSig ? 'pointer' : 'default', display: 'block' }} />
      ) : (
        <span style={{ fontSize: 14, fontWeight: 600 }}>
          {display}{rec[field.k + 'Specify'] ? <span className="t-soft"> → {rec[field.k + 'Specify']}</span> : null}
        </span>
      )}
      {signing && (
        <SignatureModal
          onClose={() => setSigning(false)}
          onDone={url => {
            setSigning(false);
            // signature implies the confirmed consent acknowledgment
            onEdit(field, url, null, { consentAck: true, consentDate: new Date().toISOString().slice(0, 10) });
          }} />
      )}
    </div>
  );
}

/* visit timeline */
function VisitTimeline({ client }) {
  const visits = window.TRELLIS_SCHEMA.visitsFor(client);
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      {visits.map((v, i) => (
        <div key={i} style={{ display: 'grid', gridTemplateColumns: '14px 1fr', gap: 14 }}>
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
            <span style={{ width: 10, height: 10, borderRadius: 99, background: v.service === 'Food' ? 'var(--gold-deep)' : 'var(--blue)', marginTop: 6, flexShrink: 0 }}></span>
            {i < visits.length - 1 && <span style={{ width: 2, flex: 1, background: 'var(--hairline)' }}></span>}
          </div>
          <div style={{ paddingBottom: 18 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
              <span className="mono" style={{ fontSize: 12.5, fontWeight: 700 }}>{v.date}</span>
              <Badge tone={v.service === 'Food' ? 'gold' : 'blue'}>{v.service}</Badge>
              {v.lbs > 0 && <span className="mono t-soft" style={{ fontSize: 12 }}>{v.lbs} lbs</span>}
            </div>
            <div className="t-faint" style={{ fontSize: 11.5, marginTop: 3 }}>Recorded by {v.by}</div>
          </div>
        </div>
      ))}
    </div>
  );
}

/* ===================== the dossier ===================== */
function ClientDossier({ client, role, onClose, push, requestAdmin }) {
  const S = window.TRELLIS_SCHEMA;
  const [rec, setRec] = React.useState(() => S.recordFor(client));
  const [section, setSection] = React.useState('identity');
  const [revealed, setRevealed] = React.useState(false);
  const [showReason, setShowReason] = React.useState(false);
  const [docView, setDocView] = React.useState(null);
  const [editing, setEditing] = React.useState(null);
  React.useEffect(() => { setRevealed(false); setShowReason(false); setEditing(null); }, [client.id, role]);

  const pct = React.useMemo(() => S.completeness(rec), [rec]);
  const canSee = revealed && role === 'admin';
  const staff = S.EHCW_STAFF.find(s => s.name === rec.caseworker);
  const active = S.SECTIONS.find(s => s.id === section);
  const relevant = sec => !sec.cat || sec.cat === rec.formCategory;

  const reveal = (reason) => {
    setRevealed(true); setShowReason(false);
    // Platform invariant: every PII reveal is audited — who, which record, why
    if (window.EHCW_DB) window.EHCW_DB.saveAuditLog('pii_reveal', client._docId || client.id, reason).catch(() => {});
    push(`PII revealed for ${client.id} — “${reason}” logged to audit trail`);
  };
  const saveField = (field, val, specify, extra) => {
    const patch = { [field.k]: val, ...(specify ? { [field.k + 'Specify']: specify } : {}), ...(extra || {}) };
    setRec(r => ({ ...r, ...patch }));
    setEditing(null);
    if (window.EHCW_DB && client._docId) {
      window.EHCW_DB.updateClient(client._docId, patch)
        .catch(e => { console.warn('[EHCW] updateClient:', e.code); push('Save failed — change is local only'); });
    }
    push(field.pii ? `${field.label} saved — masked automatically 🔒` : `${field.label} saved ✓`);
  };
  const setCategory = cat => {
    setRec(r => ({ ...r, formCategory: cat }));
    if (window.EHCW_DB && client._docId) {
      window.EHCW_DB.updateClient(client._docId, { formCategory: cat }).catch(() => {});
    }
    push(`Form Category set to ${cat} ✓`);
  };

  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 300, display: 'flex', justifyContent: 'flex-end' }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'oklch(0.12 0.02 305 / 0.4)', backdropFilter: 'blur(2px)', animation: 'trellis-pop .25s ease' }}></div>
      <div className="glass-strong" style={{
        position: 'relative', width: 'min(720px, 100%)', height: '100%', overflowY: 'auto', overscrollBehavior: 'contain',
        borderRadius: '24px 0 0 24px',
        boxShadow: '-18px 0 50px -20px oklch(0.1 0.05 305 / 0.5)', animation: 'dossier-in .4s var(--ease-spring)',
        display: 'flex', flexDirection: 'column'
      }}>
        <style>{`@keyframes dossier-in { from { transform: translateX(60px); opacity: 0; } to { transform: none; opacity: 1; } }`}</style>
        {/* header */}
        <div style={{ padding: '22px 26px 0', display: 'flex', flexDirection: 'column', gap: 16 }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', gap: 14 }}>
            <Avatar initials={client.initials} hue={parseInt(client.id.slice(3), 10) % 360} size={52} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
                <h2 style={{ fontSize: 21, fontWeight: 700, letterSpacing: '-0.02em' }}>
                  {canSee ? `${rec.firstName} ${rec.lastName || ''}`.trim() : `${rec.firstName}${rec.lastName ? ' ' + rec.lastName[0] + '.' : ''}`}
                </h2>
                <span className="mono t-faint" style={{ fontSize: 13 }}>{client.id}</span>
                <Badge tone={rec.status === 'Active' ? 'leaf' : rec.status === 'Waitlist' ? 'gold' : 'plum'}>{rec.status}</Badge>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginTop: 7, flexWrap: 'wrap' }}>
                {rec.formCategory ? (
                  <Badge tone={rec.formCategory === 'Food' ? 'gold' : rec.formCategory === 'Settlement' ? 'blue' : 'plum'}>{rec.formCategory}</Badge>
                ) : (
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                    <span style={{ fontSize: 11.5, fontWeight: 700, color: 'var(--coral)' }}>No category —</span>
                    {S.FORM_CATEGORIES.map(c => (
                      <button key={c} onClick={() => setCategory(c)} style={{ padding: '4px 10px', borderRadius: 99, fontSize: 11, fontWeight: 700, background: 'var(--coral-soft)', color: 'var(--coral)', border: '1px dashed var(--coral)' }}>{c}</button>
                    ))}
                  </span>
                )}
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7, fontSize: 12.5, fontWeight: 600 }}>
                  <StaffAvatar staff={staff} size={22} /> {rec.caseworker}
                </span>
                <span className="mono t-faint" style={{ fontSize: 12 }}>{rec.totalVisits} visits · last {rec.lastVisitDate}</span>
              </div>
            </div>
            <CompletenessRing pct={pct} />
            <button onClick={onClose} style={{ padding: 9, borderRadius: 11, background: 'var(--hover)' }}><Icon name="x" size={16} /></button>
          </div>

          {/* PII control */}
          <div className="glass" style={{ borderRadius: 14, padding: '12px 16px', display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
            <Icon name={canSee ? 'eye' : 'lock'} size={15} node={false} style={{ color: canSee ? 'var(--coral)' : 'var(--ink-faint)' }} />
            <span style={{ flex: 1, fontSize: 12.5, fontWeight: 600, minWidth: 160 }} className={canSee ? '' : 't-soft'}>
              {canSee ? 'PII visible — this session only, audit-logged.' : role === 'admin' ? 'PII masked. Reveal requires a reason.' : 'PII masked. Only an Admin can reveal.'}
            </span>
            {role === 'admin' && !revealed && (
              <button onClick={() => setShowReason(true)} style={{ padding: '8px 14px', borderRadius: 11, fontSize: 12.5, fontWeight: 700, background: 'var(--accent)', color: 'var(--accent-ink)', display: 'flex', alignItems: 'center', gap: 6, whiteSpace: 'nowrap' }}>
                <Icon name="eye" size={14} /> Reveal PII
              </button>
            )}
            {revealed && <button onClick={() => setRevealed(false)} style={{ padding: '8px 14px', borderRadius: 11, fontSize: 12.5, fontWeight: 700, background: 'var(--hover)', border: '1px solid var(--hairline-strong)' }}>Re-mask</button>}
            {role !== 'admin' && (
              <button onClick={() => requestAdmin && requestAdmin()} className="t-faint" style={{ fontSize: 12, fontWeight: 700 }}>Request access →</button>
            )}
          </div>

          {/* section rail */}
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 7, paddingBottom: 4 }}>
            {[{ id: 'visits', label: 'Visits', icon: 'calendar' }, ...S.SECTIONS].map(sec => {
              const on = section === sec.id;
              const fill = sec.id === 'visits' ? null : S.sectionFill(rec, sec);
              const dim = sec.cat && !relevant(sec);
              const dotTone = fill && fill.total ? (fill.filled === fill.total ? 'var(--leaf)' : fill.filled > 0 ? 'var(--gold-deep)' : 'var(--hairline-strong)') : null;
              return (
                <button key={sec.id} onClick={() => setSection(sec.id)} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 7, padding: '8px 13px', borderRadius: 99,
                  fontSize: 12, fontWeight: 700, opacity: dim && !on ? 0.45 : 1,
                  background: on ? 'var(--accent)' : 'var(--hover)', color: on ? 'var(--accent-ink)' : 'var(--ink-soft)',
                  border: '1px solid ' + (on ? 'transparent' : 'var(--hairline)'), transition: 'all .15s'
                }}>
                  {sec.confidential && <Icon name="shield" size={11} node={false} />}
                  {sec.label}
                  {dotTone && <span style={{ width: 6, height: 6, borderRadius: 99, background: on ? 'var(--accent-ink)' : dotTone, opacity: 0.85 }}></span>}
                </button>
              );
            })}
          </div>
        </div>

        {/* section body */}
        <div key={section} style={{ padding: '6px 26px 30px', animation: 'trellis-rise .3s ease', flex: 1 }}>
          {section === 'visits' ? (
            <div style={{ paddingTop: 14 }}><VisitTimeline client={client} /></div>
          ) : (
            <React.Fragment>
              {active.confidential && (
                <div style={{ margin: '12px 0 4px', padding: '10px 14px', borderRadius: 12, background: 'var(--coral-soft)', fontSize: 12, fontWeight: 600, display: 'flex', gap: 8, alignItems: 'center' }}>
                  <Icon name="shield" size={14} node={false} style={{ color: 'var(--coral)' }} /> Confidential — DV support details are never exported outside Admin reports.
                </div>
              )}
              {active.cat && !relevant(active) && (
                <div className="t-faint" style={{ margin: '12px 0 4px', fontSize: 12, fontWeight: 600 }}>
                  Not typical for this client&rsquo;s category ({rec.formCategory || 'unset'}) — fields remain available.
                </div>
              )}
              {active.id === 'consent' && <div style={{ paddingTop: 14 }}><IdDocumentCard client={client} role={role} revealed={revealed} push={push} requestAdmin={requestAdmin} /></div>}
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(260px, 100%), 1fr))', columnGap: 28 }}>
                {active.fields.map(f => (
                  <FieldRow key={f.k} field={f} rec={rec} canSee={canSee} role={role} push={push}
                    editing={editing} setEditing={setEditing} onEdit={saveField} />
                ))}
              </div>
              {active.id === 'consent' && (
                <div style={{ marginTop: 16, display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                  {[['docIdVerification', 'ID Verification'], ['docConsentForm', 'Consent Form'], ['docLiabilityWaiver', 'Liability Waiver']].map(([k, label]) => {
                    const count = Array.isArray(rec[k]) ? rec[k].length : (rec[k] ? 1 : 0);
                    const openDoc = () => {
                      if (!count || !client._docId) return;
                      if (!canSee) { push('Reveal PII first — document views are audit-logged'); return; }
                      setDocView([k, label]);
                    };
                    return (
                      <button key={k} onClick={openDoc} title={count ? 'Click to view' : 'Not on file'} style={{
                        display: 'inline-flex', alignItems: 'center', gap: 7, padding: '8px 14px', borderRadius: 12, fontSize: 12.5, fontWeight: 700,
                        background: count ? 'var(--leaf-soft)' : 'var(--hover)', color: count ? 'var(--leaf)' : 'var(--ink-faint)',
                        border: '1px solid var(--hairline)', cursor: count ? 'pointer' : 'default'
                      }}><Icon name={count ? 'check' : 'x'} size={12} stroke={2.4} node={false} /> {label}{count ? ` (${count})` : ''}</button>
                    );
                  })}
                </div>
              )}
            </React.Fragment>
          )}
        </div>
      </div>
      {showReason && <RevealReasonModal client={client} onConfirm={reveal} onClose={() => setShowReason(false)} />}
      {docView && <DocLightbox client={client} field={docView[0]} label={docView[1]} onClose={() => setDocView(null)} />}
    </div>
  );
}

Object.assign(window, { ClientDossier, CompletenessRing, StaffAvatar });
