function hslToHex(h,s,l){ s/=100;l/=100; const k=n=>(n+h/30)%12, a=s*Math.min(l,1-l), f=n=>l-a*Math.max(-1,Math.min(k(n)-3,Math.min(9-k(n),1)));
  const to=x=>Math.round(255*x).toString(16).padStart(2,'0'); return '#'+to(f(0))+to(f(8))+to(f(4)); }
function ColorPicker({ value, onChange }) {
  const [hue,setHue] = React.useState(215);
  const [light,setLight] = React.useState(45);
  React.useEffect(()=>{ onChange(hslToHex(hue,70,light)); },[hue,light]);
  return <div style={{display:'flex',flexDirection:'column',gap:10,padding:14,background:'var(--sitm-bg-light-dim)',border:'1px solid var(--sitm-border)',borderRadius:10}}>
    <div style={{display:'flex',alignItems:'center',gap:12}}>
      <div style={{width:38,height:38,borderRadius:9,background:value,border:'1px solid rgba(0,0,0,.08)',flex:'none'}}></div>
      <div style={{flex:1,display:'flex',flexDirection:'column',gap:8}}>
        <input type="range" min="0" max="360" value={hue} onChange={e=>setHue(parseInt(e.target.value))}
          style={{width:'100%',height:12,appearance:'none',WebkitAppearance:'none',borderRadius:6,outline:'none',cursor:'pointer',
            background:'linear-gradient(90deg,#e34040,#e3d940,#4ce340,#40e3d9,#4059e3,#d940e3,#e34040)'}}/>
        <input type="range" min="20" max="80" value={light} onChange={e=>setLight(parseInt(e.target.value))}
          style={{width:'100%',height:12,appearance:'none',WebkitAppearance:'none',borderRadius:6,outline:'none',cursor:'pointer',
            background:'linear-gradient(90deg, '+hslToHex(hue,70,20)+', '+hslToHex(hue,70,50)+', '+hslToHex(hue,70,80)+')'}}/>
      </div>
      <span style={{fontSize:12,fontWeight:600,color:'var(--sitm-text)',width:64}}>{value}</span>
    </div>
    <div style={{display:'flex',gap:6,alignItems:'center'}}>
      <span style={{fontSize:11,color:'var(--sitm-text)'}}>Brand</span>
      {CS_PALETTE.filter(([n])=>n!=='White').map(([n,c])=><Swatch key={c} color={c} size={18} active={value===c} onClick={()=>onChange(c)}/>)}
    </div>
  </div>;
}
function ShortcutField({ value, onChange }) {
  const [listening,setListening] = React.useState(false);
  const label = listening ? 'Press a key...' : value;
  return <button onClick={()=>setListening(true)} onBlur={()=>setListening(false)}
    onKeyDown={(e)=>{ if(!listening) return; e.preventDefault();
      const parts = []; if(e.ctrlKey) parts.push('Ctrl'); if(e.metaKey) parts.push('Cmd'); if(e.shiftKey) parts.push('Shift'); if(e.altKey) parts.push('Alt');
      if(!['Control','Meta','Shift','Alt'].includes(e.key)) { parts.push(e.key==='Backspace'?'Backspace':e.key.length===1?e.key.toUpperCase():e.key); onChange(parts.join(' + ')); setListening(false); } }}
    style={{fontFamily:'var(--sitm-font-body)',fontSize:13,fontWeight:600,padding:'9px 16px',cursor:'pointer',borderRadius:8,minWidth:150,
      border:listening?'2px solid var(--sitm-teal)':'1px solid var(--sitm-border)',background:listening?'rgba(97,189,183,.08)':'#fff',color:'var(--sitm-navy)'}}>
    {label}
  </button>;
}
// shared engine: auto-color rules inside any contentEditable root, with caret preservation
const csWordStyle = {
  caretOffset(root) {
    const sel = window.getSelection();
    if (!sel || !sel.anchorNode || !root.contains(sel.anchorNode) || !sel.isCollapsed) return null;
    const r = document.createRange(); r.selectNodeContents(root); r.setEnd(sel.anchorNode, sel.anchorOffset);
    return r.toString().length;
  },
  restoreCaret(root, offset) {
    if (offset == null) return;
    const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
    let n, acc = 0;
    while (n = walker.nextNode()) {
      const len = n.textContent.length;
      if (acc + len >= offset) { const sel = window.getSelection(); const r = document.createRange();
        r.setStart(n, offset - acc); r.collapse(true); sel.removeAllRanges(); sel.addRange(r); return; }
      acc += len;
    }
    const sel = window.getSelection(); const r = document.createRange(); r.selectNodeContents(root); r.collapse(false);
    sel.removeAllRanges(); sel.addRange(r);
  },
  applyRules(root, rules, ctx) {
    ctx = ctx || {};
    const active = rules.filter(r => r.enabled && r.term.trim() &&
      (ctx.ignoreConditions || !r.collection || r.collection === 'Any collection' || r.collection === ctx.collection));
    if (!active.length) return;
    const caret = this.caretOffset(root);
    const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
    const nodes = []; let n; while (n = walker.nextNode()) nodes.push(n);
    let changed = false;
    nodes.forEach(node => {
      const parent = node.parentElement;
      if (!parent || parent.closest('[data-auto],[data-skip]')) return;
      for (const r of active) {
        if (!ctx.ignoreConditions && r.onlyBold) {
          const w = parseInt(getComputedStyle(parent).fontWeight) || 400; if (w < 600) continue;
        }
        const re = new RegExp('(^|[^A-Za-z0-9])(' + r.term.replace(/[.*+?^\${}()|[\]\\]/g,'\\$&') + ')(?=$|[^A-Za-z0-9])','i');
        const m = node.textContent.match(re);
        if (m && m.index != null) {
          const start = m.index + m[1].length;
          const word = node.splitText(start); word.splitText(m[2].length);
          const span = document.createElement('span');
          span.setAttribute('data-auto','1'); span.style.color = r.color; if (r.bold) span.style.fontWeight = '700';
          word.parentNode.replaceChild(span, word); span.appendChild(word);
          changed = true; break;
        }
      }
    });
    if (changed) this.restoreCaret(root, caret);
  },
  handleUndoKey(e, shortcut) {
    if (!matchesShortcut(e, shortcut)) return false;
    const sel = window.getSelection(); if (!sel || !sel.anchorNode) return false;
    let el = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentElement : sel.anchorNode;
    let auto = el && el.closest && el.closest('[data-auto]');
    if (!auto && sel.anchorNode.nodeType === 3 && sel.anchorOffset === 0) {
      const prev = sel.anchorNode.previousSibling; if (prev && prev.nodeType === 1 && prev.getAttribute('data-auto')) auto = prev;
    }
    if (!auto && el) { const prev = el.previousElementSibling; if (prev && prev.getAttribute && prev.getAttribute('data-auto') && sel.anchorOffset === 0) auto = prev; }
    if (!auto) return false;
    e.preventDefault();
    const plain = document.createElement('span'); plain.setAttribute('data-skip','1'); plain.textContent = auto.textContent;
    auto.parentNode.replaceChild(plain, auto);
    const s2 = window.getSelection(); const r = document.createRange(); r.selectNodeContents(plain); r.collapse(false);
    s2.removeAllRanges(); s2.addRange(r);
    return true;
  }
};
function matchesShortcut(e, sc) {
  const parts = sc.split(' + ');
  const key = parts[parts.length-1];
  const need = { ctrl:parts.includes('Ctrl'), meta:parts.includes('Cmd'), shift:parts.includes('Shift'), alt:parts.includes('Alt') };
  if (e.ctrlKey!==need.ctrl || e.metaKey!==need.meta || e.shiftKey!==need.shift || e.altKey!==need.alt) return false;
  return e.key===key || e.key.toUpperCase()===key || (key==='Backspace'&&e.key==='Backspace');
}
function TryItBox({ rules, shortcut }) {
  const ref = React.useRef(null);
  const onKeyUp2 = (e) => { if (e.key===' ' || [',','.','!','?',';',':','Enter'].includes(e.key)) csWordStyle.applyRules(ref.current, rules, {ignoreConditions:true}); };
  const onKeyDown2 = (e) => { csWordStyle.handleUndoKey(e, shortcut); };

  return <div>
    <div contentEditable suppressContentEditableWarning ref={ref} onKeyUp={onKeyUp2} onKeyDown={onKeyDown2}
      style={{minHeight:64,padding:'12px 14px',background:'#fff',border:'1px solid rgba(62,71,97,.2)',borderRadius:10,fontFamily:'var(--sitm-font-body)',fontSize:14,lineHeight:1.6,color:'var(--sitm-text-price)',outline:'none'}}></div>
    <div style={{fontSize:11.5,color:'var(--sitm-text)',marginTop:7,lineHeight:1.5}}>Type a sentence with one of your words in it. The color lands when you hit space or punctuation. Press <b>{shortcut}</b> right after to undo just the color. Rules with conditions follow them in the editor.</div>
  </div>;
}
function SettingsCard({ title, sub, children }) {
  return <div style={{background:'#fff',border:'1px solid var(--sitm-border)',borderRadius:14,padding:24,marginBottom:18}}>
    <div style={{fontFamily:'var(--sitm-font-heading)',fontSize:18,color:'var(--sitm-navy)'}}>{title}</div>
    <Sub style={{marginTop:5,marginBottom:16,maxWidth:640}}>{sub}</Sub>
    {children}
  </div>;
}
function SettingsPage({ rules, setRules, shortcut, setShortcut, collections, setCollections, toast }) {
  const [term,setTerm] = React.useState('');
  const [color,setColor] = React.useState('#2f6fd0');
  const [onlyBold,setOnlyBold] = React.useState(false);
  const [alsoBold,setAlsoBold] = React.useState(false);
  const [coll,setColl] = React.useState('Any collection');
  const [newColl,setNewColl] = React.useState('');
  const [editColl,setEditColl] = React.useState(null);
  const addRule = ()=>{ if(!term.trim()) return;
    setRules(r=>[...r,{id:Date.now(),term:term.trim(),color,bold:alsoBold,onlyBold,collection:coll,enabled:true}]);
    setTerm(''); toast('Added. '+term.trim()+' now colors itself as you type.'); };
  return <div style={{maxWidth:900,margin:'0 auto',padding:'36px 28px 80px'}}>
    <PageHead kicker="Settings" title="Make the studio yours"
      sub="Everything here applies across the whole studio. More settings will land as the studio grows."/>
    <SettingsCard title="Words that style themselves" sub="Add a word or phrase and pick its color. Any time you type it, it takes that style the moment you hit space or punctuation. One keypress undoes it for a single spot.">
      {rules.length>0 && <div style={{border:'1px solid var(--sitm-border)',borderRadius:10,overflow:'hidden',marginBottom:16}}>
        {rules.map((r,i)=><div key={r.id} style={{display:'flex',alignItems:'center',gap:12,padding:'10px 14px',borderTop:i?'1px solid var(--sitm-border)':'none',opacity:r.enabled?1:.45}}>
          <span style={{width:16,height:16,borderRadius:5,background:r.color,flex:'none',border:'1px solid rgba(0,0,0,.08)'}}></span>
          <span style={{fontSize:13.5,fontWeight:r.bold?700:600,color:r.color,minWidth:110}}>{r.term}</span>
          <span style={{fontSize:11.5,color:'var(--sitm-text)',flex:1}}>
            {[r.onlyBold?'only when bolded':null, r.collection!=='Any collection'?'only in '+r.collection:null, r.bold?'also bolds it':null].filter(Boolean).join(' \u00b7 ') || 'everywhere'}
          </span>
          <button onClick={()=>setRules(x=>x.map(y=>y.id===r.id?{...y,enabled:!y.enabled}:y))}
            style={{width:32,height:18,borderRadius:10,flex:'none',position:'relative',border:'none',cursor:'pointer',transition:'background .2s ease',background:r.enabled?'var(--sitm-teal)':'rgba(62,71,97,.25)'}}>
            <span style={{position:'absolute',top:2,left:r.enabled?16:2,width:14,height:14,borderRadius:'50%',background:'#fff',transition:'left .2s ease'}}></span>
          </button>
          <DeleteBtn onClick={()=>setRules(x=>x.filter(y=>y.id!==r.id))}/>
        </div>)}
      </div>}
      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:16,alignItems:'start'}}>
        <div style={{display:'flex',flexDirection:'column',gap:12}}>
          <div>
            <div style={{fontSize:12.5,fontWeight:600,marginBottom:6}}>Word or phrase</div>
            <input value={term} onChange={e=>setTerm(e.target.value)} placeholder="Wavelength"
              style={{width:'100%',boxSizing:'border-box',fontFamily:'var(--sitm-font-body)',fontSize:14,padding:'9px 12px',border:'1px solid rgba(62,71,97,.2)',borderRadius:8,outline:'none',color:'var(--sitm-text)'}}/>
          </div>
          <div style={{display:'flex',flexDirection:'column',gap:8}}>
            <label style={{display:'flex',alignItems:'center',gap:9,fontSize:13,cursor:'pointer'}}>
              <input type="checkbox" checked={onlyBold} onChange={e=>setOnlyBold(e.target.checked)} style={{accentColor:'var(--sitm-teal)',width:15,height:15}}/>Only when it is bolded
            </label>
            <label style={{display:'flex',alignItems:'center',gap:9,fontSize:13,cursor:'pointer'}}>
              <input type="checkbox" checked={alsoBold} onChange={e=>setAlsoBold(e.target.checked)} style={{accentColor:'var(--sitm-teal)',width:15,height:15}}/>Also make it bold
            </label>
            <div style={{display:'flex',alignItems:'center',gap:9,fontSize:13}}>
              Only in
              <span style={{position:'relative',display:'inline-block',flex:1}}>
                <select value={coll} onChange={e=>setColl(e.target.value)} style={{width:'100%',appearance:'none',WebkitAppearance:'none',fontFamily:'var(--sitm-font-body)',fontSize:12.5,padding:'7px 26px 7px 10px',background:'#fff',border:'1px solid var(--sitm-border)',borderRadius:8,cursor:'pointer',color:'var(--sitm-text)'}}>
                  {['Any collection',...collections.map(c=>c.name)].map(c=><option key={c} value={c}>{c}</option>)}
                </select>
                <span style={{position:'absolute',right:8,top:'50%',transform:'translateY(-50%)',pointerEvents:'none',color:'var(--sitm-text)'}}><Icon name="chevR" size={11} style={{transform:'rotate(90deg)'}}/></span>
              </span>
            </div>
          </div>
          <Btn size="sm" disabled={!term.trim()} onClick={addRule} style={{alignSelf:'flex-start'}}>Add this word</Btn>
        </div>
        <ColorPicker value={color} onChange={setColor}/>
      </div>
      <div style={{marginTop:18,borderTop:'1px solid var(--sitm-border)',paddingTop:16}}>
        <div style={{fontSize:12.5,fontWeight:600,marginBottom:8}}>Try it here</div>
        <TryItBox rules={rules} shortcut={shortcut}/>
      </div>
    </SettingsCard>
    <SettingsCard title="The undo keypress" sub="When a word colors itself and you did not want it this one time, this key undoes the color instead of deleting the letter. Click the box and press the key you want.">
      <div style={{display:'flex',alignItems:'center',gap:14}}>
        <ShortcutField value={shortcut} onChange={(v)=>{setShortcut(v);toast('Saved. '+v+' now undoes the color.');}}/>
        <span style={{fontSize:12.5,color:'var(--sitm-text)'}}>Right now: press <b>{shortcut}</b> right after a word colors itself.</span>
      </div>
    </SettingsCard>
    <SettingsCard title="Collection colors" sub="Each collection gets its own color. Materials made from that collection lean on it for headers, accents, and word styles. This will grow into full theming.">
      <div style={{border:'1px solid var(--sitm-border)',borderRadius:10,overflow:'hidden',marginBottom:14}}>
        {collections.map((c,i)=><div key={c.name} style={{borderTop:i?'1px solid var(--sitm-border)':'none'}}>
          <div style={{display:'flex',alignItems:'center',gap:12,padding:'10px 14px'}}>
            <button onClick={()=>setEditColl(editColl===c.name?null:c.name)} title="Change color"
              style={{width:26,height:26,borderRadius:8,background:c.color,border:'1px solid rgba(0,0,0,.08)',cursor:'pointer',flex:'none'}}></button>
            <span style={{fontSize:13.5,fontWeight:600,color:'var(--sitm-navy)',flex:1}}>{c.name}</span>
            <span style={{fontSize:11.5,color:'var(--sitm-text)'}}>{c.color}</span>
            <DeleteBtn onClick={()=>setCollections(x=>x.filter(y=>y.name!==c.name))}/>
          </div>
          {editColl===c.name && <div style={{padding:'0 14px 14px'}}>
            <ColorPicker value={c.color} onChange={(v)=>setCollections(x=>x.map(y=>y.name===c.name?{...y,color:v}:y))}/>
          </div>}
        </div>)}
      </div>
      <div style={{display:'flex',gap:8,maxWidth:420}}>
        <input value={newColl} onChange={e=>setNewColl(e.target.value)} placeholder="New collection, like Pediatric"
          style={{flex:1,fontFamily:'var(--sitm-font-body)',fontSize:13,padding:'8px 11px',border:'1px solid rgba(62,71,97,.2)',borderRadius:8,outline:'none',color:'var(--sitm-text)'}}/>
        <Btn size="sm" disabled={!newColl.trim()} onClick={()=>{setCollections(x=>[...x,{name:newColl.trim(),color:'#61bdb7'}]);setNewColl('');}}>Add</Btn>
      </div>
    </SettingsCard>
  </div>;
}
Object.assign(window, { SettingsPage, ColorPicker, ShortcutField, TryItBox, csWordStyle, matchesShortcut });
