// ViewConfig.jsx — dashboard view configurator
// A "view" = named arrangement of sub-modules, general or patient-scoped.
// Sub-modules are finer-grained than the 4 classic panels.

const { useState: useVC, useEffect: useVCEffect } = React;

// ── Sub-module catalogue ────────────────────────────────────────────────────
// parent groups correspond to the original 4 panels.
// `title` = short header label (shown on the tile). `desc` = longer descriptor (config modal).
// `defaultSpan` = default column span (1–12) on the 12-col grid.
const MODULE_CATALOGUE = [
  // Panel 1 – Clinical Snapshot
  { id:'snap.vitals',     parent:'Clinical Snapshot',   title:'Vital metrics',             desc:'eGFR, creatinine, cystatin C, UACR, BP, CKD',   defaultSpan:6 },
  { id:'snap.egfrchart',  parent:'Clinical Snapshot',   title:'eGFR trajectory',           desc:'Annual eGFR trend (chart)',                     defaultSpan:6 },
  { id:'snap.family',     parent:'Clinical Snapshot',   title:'Family history',            desc:'Inherited ADPKD context strip',                 defaultSpan:6 },
  // Panel 2 – Imaging & Volumetry
  { id:'img.metrics',     parent:'Imaging & Volumetry', title:'TKV metrics',               desc:'htTKV and growth rate',                         defaultSpan:6 },
  { id:'img.mayoband',    parent:'Imaging & Volumetry', title:'Mayo Classification',       desc:'Imaging class band',                            defaultSpan:6 },
  { id:'img.tkvchart',    parent:'Imaging & Volumetry', title:'htTKV trajectory',          desc:'TKV trend over time',                           defaultSpan:6 },
  { id:'img.pacs',        parent:'Imaging & Volumetry', title:'PACS preview',              desc:'AI-segmented kidney volume',                    defaultSpan:6 },
  // Panel 3 – Genetics
  { id:'gen.variant',     parent:'Genetics',            title:'Identified variant',        desc:'PKD variant + c./p. notation',                  defaultSpan:6 },
  { id:'gen.acmg',        parent:'Genetics',            title:'ACMG pathogenicity',        desc:'Class band (Benign → Pathogenic)',              defaultSpan:6 },
  { id:'gen.compare',     parent:'Genetics',            title:'Prognostic context',        desc:'PKD1 vs PKD2 comparison grid',                  defaultSpan:6 },
  { id:'gen.consent',     parent:'Genetics',            title:'Counselling & consent',     desc:'Genetic counselling + DIZ consent stamp',       defaultSpan:6 },
  // Panel 4 – Decision Assistant (rendered as one cohesive tile)
  { id:'dec.full',        parent:'Decision Assistant',  title:'Tolvaptan Decision',        desc:'Eligibility, criteria, what-if, actions',       defaultSpan:12 },
];

// All sub-module IDs
const ALL_MODULE_IDS = MODULE_CATALOGUE.map(m=>m.id);

// Legal spans on the 12-col grid
const SPAN_OPTIONS = [
  { v:3,  label:'¼',    desc:'Quarter' },
  { v:4,  label:'⅓',    desc:'Third' },
  { v:6,  label:'½',    desc:'Half' },
  { v:8,  label:'⅔',    desc:'Two thirds' },
  { v:12, label:'Full', desc:'Full width' },
];

// Normalise a view's modules array to [{id, span}]
function normalizeModules(mods) {
  if (!Array.isArray(mods)) return [];
  return mods.map(m => {
    if (typeof m === 'string') {
      const def = MODULE_CATALOGUE.find(c=>c.id===m);
      return { id:m, span: def?.defaultSpan ?? 6 };
    }
    return { id:m.id, span: m.span || (MODULE_CATALOGUE.find(c=>c.id===m.id)?.defaultSpan ?? 6) };
  }).filter(m => MODULE_CATALOGUE.some(c=>c.id===m.id));
}

// ── Seed views ──────────────────────────────────────────────────────────────
// Each module is {id, span} on a 12-col grid. Spans 3/4/6/8/12 are legal.
const SEED_VIEWS = [
  {
    id:'seed-full', name:'Full Dashboard', scope:'general', seed:true,
    modules: [
      {id:'snap.vitals', span:6}, {id:'img.metrics', span:6},
      {id:'snap.egfrchart', span:6}, {id:'img.tkvchart', span:6},
      {id:'img.mayoband', span:6}, {id:'img.pacs', span:6},
      {id:'gen.variant', span:6}, {id:'gen.acmg', span:6},
      {id:'gen.compare', span:6}, {id:'gen.consent', span:6},
      {id:'snap.family', span:12},
      {id:'dec.full', span:12},
    ],
  },
  {
    id:'seed-tolvaptan', name:'Tolvaptan Review', scope:'general', seed:true,
    modules: [
      {id:'snap.vitals', span:6}, {id:'snap.egfrchart', span:6},
      {id:'gen.variant', span:12},
      {id:'dec.full', span:12},
    ],
  },
  {
    id:'seed-imaging', name:'Imaging-focused', scope:'general', seed:true,
    modules: [
      {id:'img.metrics', span:4}, {id:'img.mayoband', span:8},
      {id:'img.tkvchart', span:6}, {id:'img.pacs', span:6},
      {id:'snap.vitals', span:12},
    ],
  },
];

// ── Store ───────────────────────────────────────────────────────────────────
// Bump the key whenever the module catalogue / seed shape changes, so old
// (incompatible) cached views from earlier prototypes don't hide modules.
const VIEW_STORE_KEY = '__dicecd_views_v3__';

function loadViews() {
  try {
    const raw = sessionStorage.getItem(VIEW_STORE_KEY);
    if (raw) {
      const cached = JSON.parse(raw);
      // Always merge in current SEED_VIEWS so newly-added defaults appear.
      const cachedSeedIds = new Set(cached.filter(v=>v.seed).map(v=>v.id));
      const missingSeeds = SEED_VIEWS.filter(v => !cachedSeedIds.has(v.id));
      // Also refresh any seed view: we're the source of truth for their modules.
      const merged = cached.map(v => {
        if (!v.seed) return v;
        const current = SEED_VIEWS.find(s=>s.id===v.id);
        return current || v;
      });
      return [...merged, ...missingSeeds];
    }
  } catch(e) {}
  return SEED_VIEWS;
}
function saveViews(views) {
  try { sessionStorage.setItem(VIEW_STORE_KEY, JSON.stringify(views)); } catch(e) {}
}

// ── Public hook ─────────────────────────────────────────────────────────────
function useViews() {
  const [views, setViews] = useVC(loadViews);
  useVCEffect(() => { saveViews(views); }, [views]);
  return [views, setViews];
}

function availableViewsFor(views, patientId) {
  return views.filter(v => v.scope==='general' || v.scope===`patient:${patientId}`);
}

// ── Configure modal ────────────────────────────────────────────────────────
function ConfigureModal({ open, onClose, views, setViews, activeViewId, setActiveViewId, patient, editingId }) {
  // Start blank unless editing
  const editingView = editingId ? views.find(v=>v.id===editingId) : null;
  const [name, setName] = useVC('');
  const [scope, setScope] = useVC('general'); // 'general' or 'patient'
  // selected: Map<id, span>
  const [selected, setSelected] = useVC(new Map());

  // Reset when opened or switching target
  useVCEffect(() => {
    if (!open) return;
    if (editingView) {
      setName(editingView.name);
      setScope(editingView.scope==='general'?'general':'patient');
      const m = new Map();
      normalizeModules(editingView.modules).forEach(({id,span}) => m.set(id,span));
      setSelected(m);
    } else {
      setName('');
      setScope('general');
      setSelected(new Map());
    }
  }, [open, editingId]);

  if (!open) return null;

  function toggle(id) {
    const m = new Map(selected);
    if (m.has(id)) m.delete(id);
    else {
      const def = MODULE_CATALOGUE.find(c=>c.id===id);
      m.set(id, def?.defaultSpan ?? 6);
    }
    setSelected(m);
  }
  function setSpan(id, span) {
    const m = new Map(selected);
    if (m.has(id)) m.set(id, span);
    setSelected(m);
  }
  function toggleGroup(parent) {
    const ids = MODULE_CATALOGUE.filter(m=>m.parent===parent).map(m=>m.id);
    const allOn = ids.every(id=>selected.has(id));
    const m = new Map(selected);
    if (allOn) ids.forEach(id=>m.delete(id));
    else ids.forEach(id=>{
      if (!m.has(id)) {
        const def = MODULE_CATALOGUE.find(c=>c.id===id);
        m.set(id, def?.defaultSpan ?? 6);
      }
    });
    setSelected(m);
  }

  function save() {
    const nm = name.trim() || 'Untitled View';
    const mods = Array.from(selected.entries()).map(([id,span]) => ({id,span}));
    if (mods.length === 0) { alert('Pick at least one module.'); return; }
    const realScope = scope==='general' ? 'general' : `patient:${patient.id}`;
    if (editingView) {
      setViews(views.map(v => v.id===editingView.id ? {...v, name:nm, scope:realScope, modules:mods} : v));
      setActiveViewId(editingView.id);
    } else {
      const id = `v-${Date.now()}`;
      setViews([...views, { id, name:nm, scope:realScope, modules:mods, createdAt:new Date().toISOString() }]);
      setActiveViewId(id);
    }
    onClose();
  }
  function del() {
    if (!editingView) return;
    if (editingView.seed) { alert('Seed views cannot be deleted.'); return; }
    if (!confirm(`Delete view "${editingView.name}"?`)) return;
    setViews(views.filter(v=>v.id!==editingView.id));
    if (activeViewId === editingView.id) setActiveViewId('seed-full');
    onClose();
  }

  const parents = Array.from(new Set(MODULE_CATALOGUE.map(m=>m.parent)));

  return (
    <div style={{position:'fixed', inset:0, zIndex:300, background:'rgba(26,26,26,0.32)', display:'flex', alignItems:'center', justifyContent:'center'}} onClick={onClose}>
      <div onClick={e=>e.stopPropagation()} style={{background:'#fff', borderRadius:6, width:720, maxHeight:'90vh', display:'flex', flexDirection:'column', overflow:'hidden', boxShadow:'0 8px 40px rgba(0,0,0,0.22)'}}>
        <div style={{padding:'16px 20px', borderBottom:'1px solid #E5E5E7', display:'flex', alignItems:'center', justifyContent:'space-between'}}>
          <div>
            <div style={{fontSize:10, fontWeight:700, color:'#AEAEB2', textTransform:'uppercase', letterSpacing:'0.06em'}}>Dashboard Views</div>
            <div style={{fontSize:15, fontWeight:700, color:'#1A1A1A', marginTop:2}}>{editingView?'Edit view':'Create a new view'}</div>
          </div>
          <button onClick={onClose} style={{background:'transparent', border:'none', fontSize:20, color:'#4A4A4A', cursor:'pointer'}}>×</button>
        </div>

        <div style={{flex:1, overflowY:'auto', padding:20}}>
          {/* Name + scope */}
          <div style={{display:'grid', gridTemplateColumns:'2fr 1.3fr', gap:16, marginBottom:18}}>
            <div>
              <div style={{fontSize:10, fontWeight:700, color:'#4A4A4A', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:5}}>Name</div>
              <input value={name} onChange={e=>setName(e.target.value)} placeholder="e.g. Hypertension follow-up"
                style={{width:'100%', padding:'8px 10px', border:'1px solid #E5E5E7', borderRadius:4, fontSize:13, outline:'none'}}/>
            </div>
            <div>
              <div style={{fontSize:10, fontWeight:700, color:'#4A4A4A', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:5}}>Scope</div>
              <div style={{display:'flex', gap:6}}>
                <label style={scopeRadioStyle(scope==='general')}>
                  <input type="radio" checked={scope==='general'} onChange={()=>setScope('general')} style={{marginRight:5}}/>
                  General
                </label>
                <label style={scopeRadioStyle(scope==='patient')}>
                  <input type="radio" checked={scope==='patient'} onChange={()=>setScope('patient')} style={{marginRight:5}}/>
                  Pin to {patient.alias}
                </label>
              </div>
            </div>
          </div>

          {/* Module picker */}
          <div style={{fontSize:10, fontWeight:700, color:'#4A4A4A', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:6}}>Modules · pick any combination · set width</div>
          <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:12}}>
            {parents.map(parent => {
              const items = MODULE_CATALOGUE.filter(m=>m.parent===parent);
              const onCount = items.filter(m=>selected.has(m.id)).length;
              return (
                <div key={parent} style={{border:'1px solid #E5E5E7', borderRadius:5, overflow:'hidden'}}>
                  <div onClick={()=>toggleGroup(parent)} style={{padding:'8px 12px', background:'#FAFAFA', display:'flex', alignItems:'center', justifyContent:'space-between', cursor:'pointer', borderBottom:'1px solid #E5E5E7'}}>
                    <div style={{fontSize:12, fontWeight:700, color:'#1A1A1A'}}>{parent}</div>
                    <div style={{fontSize:10, color:'#4A4A4A'}}>{onCount}/{items.length}</div>
                  </div>
                  <div style={{padding:'6px 10px'}}>
                    {items.map(m => {
                      const isOn = selected.has(m.id);
                      const span = selected.get(m.id) || m.defaultSpan;
                      return (
                        <div key={m.id} style={{padding:'6px 2px', borderBottom:'1px solid #F5F5F5'}}>
                          <label style={{display:'flex', alignItems:'flex-start', gap:8, cursor:'pointer'}}>
                            <input type="checkbox" checked={isOn} onChange={()=>toggle(m.id)} style={{marginTop:2, accentColor:'#D32027'}}/>
                            <div style={{flex:1, minWidth:0}}>
                              <div style={{fontSize:11, color:'#1A1A1A', fontWeight:600, lineHeight:1.3}}>{m.title}</div>
                              <div style={{fontSize:10, color:'#AEAEB2', lineHeight:1.3}}>{m.desc}</div>
                            </div>
                          </label>
                          {isOn && (
                            <div style={{display:'flex', gap:2, marginTop:5, marginLeft:24}}>
                              {SPAN_OPTIONS.map(o => (
                                <button key={o.v} onClick={()=>setSpan(m.id, o.v)} title={o.desc} style={{
                                  padding:'2px 7px', fontSize:9, fontWeight:700, borderRadius:2, cursor:'pointer',
                                  background: span===o.v ? '#1A1A1A' : '#fff',
                                  color:      span===o.v ? '#fff' : '#4A4A4A',
                                  border:     span===o.v ? '1px solid #1A1A1A' : '1px solid #E5E5E7',
                                }}>{o.label}</button>
                              ))}
                            </div>
                          )}
                        </div>
                      );
                    })}
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        <div style={{padding:'12px 20px', borderTop:'1px solid #E5E5E7', display:'flex', justifyContent:'space-between', gap:8, background:'#FAFAFA'}}>
          <div>
            {editingView && !editingView.seed && (
              <button onClick={del} style={{padding:'8px 14px', background:'transparent', color:'#D32027', border:'1px solid #D3202740', borderRadius:4, fontSize:12, fontWeight:600, cursor:'pointer'}}>Delete view</button>
            )}
          </div>
          <div style={{display:'flex', gap:8}}>
            <button onClick={onClose} style={{padding:'8px 14px', background:'#fff', color:'#4A4A4A', border:'1px solid #E5E5E7', borderRadius:4, fontSize:12, fontWeight:600, cursor:'pointer'}}>Cancel</button>
            <button onClick={save} style={{padding:'8px 16px', background:'#1A1A1A', color:'#fff', border:'none', borderRadius:4, fontSize:12, fontWeight:700, cursor:'pointer'}}>{editingView?'Save changes':'Save view'}</button>
          </div>
        </div>
      </div>
    </div>
  );
}

function scopeRadioStyle(active) {
  return {
    flex:1, display:'flex', alignItems:'center', padding:'7px 10px', borderRadius:4, cursor:'pointer',
    fontSize:11, fontWeight:600, color: active?'#1A1A1A':'#4A4A4A',
    border: active?'2px solid #1A1A1A':'1px solid #E5E5E7',
    background: active?'#F7F7F8':'#fff',
  };
}

// ── View selector pill bar ──────────────────────────────────────────────────
function ViewSelector({ views, activeViewId, setActiveViewId, patient, onConfigure, onEdit }) {
  const available = availableViewsFor(views, patient.id);
  return (
    <div style={{display:'flex', alignItems:'center', gap:6, flexWrap:'wrap'}}>
      <span style={{fontSize:10, fontWeight:700, color:'#AEAEB2', textTransform:'uppercase', letterSpacing:'0.06em', marginRight:2}}>View</span>
      {available.map(v => {
        const isActive = v.id === activeViewId;
        const isPatient = v.scope !== 'general';
        return (
          <div key={v.id} style={{position:'relative', display:'flex'}}>
            <button onClick={()=>setActiveViewId(v.id)} style={{
              padding:'5px 10px 5px 10px', borderRadius:3,
              fontSize:11, fontWeight:600, cursor:'pointer',
              background: isActive?'#1A1A1A':'#fff',
              color:      isActive?'#fff':'#1A1A1A',
              border:     isActive?'1px solid #1A1A1A':'1px solid #E5E5E7',
              display:'flex', alignItems:'center', gap:6,
            }}>
              {isPatient && <span style={{fontSize:9, padding:'1px 4px', borderRadius:2, background: isActive?'#D32027':'#FEF2F2', color: isActive?'#fff':'#D32027', fontWeight:700}}>●</span>}
              {v.name}
              <span style={{fontSize:9, opacity:0.65}}>· {v.modules.length}</span>
              {!v.seed && (
                <span onClick={e=>{e.stopPropagation(); onEdit(v.id);}} style={{marginLeft:3, opacity:0.6, fontSize:11}}>✎</span>
              )}
            </button>
          </div>
        );
      })}
      <button onClick={onConfigure} style={{
        padding:'5px 10px', borderRadius:3, fontSize:11, fontWeight:600, cursor:'pointer',
        background:'#fff', color:'#D32027', border:'1px dashed #D32027',
        display:'flex', alignItems:'center', gap:4,
      }}>+ New view</button>
    </div>
  );
}

Object.assign(window, {
  MODULE_CATALOGUE, ALL_MODULE_IDS, SPAN_OPTIONS, normalizeModules,
  availableViewsFor, useViews, ConfigureModal, ViewSelector,
});
