// OS Builder — reusable control primitives.
// Pill-card pickers, sliders, segmented controls, drag-rank list, toggle rows, etc.

/* =========== TONE TOKEN HELPERS =========== */
const OS_TONES = {
  chart: { bg:'var(--chart-100)', bgSoft:'var(--chart-50)', fg:'var(--chart-900)', ring:'var(--chart-500)' },
  lilac: { bg:'var(--lilac-100)', bgSoft:'var(--lilac-50)', fg:'var(--lilac-800)', ring:'var(--lilac-500)' },
};

/* =========== PICKER CARD (single & multi) =========== */
function OSCardPicker({ items, value, onChange, multi=false, cols=3, render, tone='lilac', minH=78 }) {
  const sel = multi ? new Set(value || []) : value;
  const toggle = (id) => {
    if (multi) {
      const next = new Set(sel);
      next.has(id) ? next.delete(id) : next.add(id);
      onChange(Array.from(next));
    } else {
      onChange(id);
    }
  };
  const T = OS_TONES[tone];
  return (
    <div style={{ display:'grid', gridTemplateColumns:`repeat(${cols}, minmax(0,1fr))`, gap:10 }}>
      {items.map(it => {
        const id = it.id || it;
        const active = multi ? sel.has(id) : sel === id;
        return (
          <button key={id} onClick={()=>toggle(id)} type="button" style={{
            position:'relative', textAlign:'left', cursor:'pointer',
            padding:'14px 16px', minHeight:minH,
            background: active ? T.bg : 'var(--paper)',
            border: '1px solid', borderColor: active ? T.ring : 'var(--line)',
            borderRadius:14, transition:'all .15s ease',
            boxShadow: active ? `0 0 0 3px ${T.bgSoft}` : 'none',
            fontFamily:'var(--font-body)',
          }}>
            {render ? render(it, active) : (
              <>
                <div style={{ fontSize:14, fontWeight:600, color:'var(--ink)', letterSpacing:'-0.01em' }}>{it.label || it.name || it}</div>
                {it.tag && <div style={{ fontSize:11.5, color: active ? T.fg : 'var(--mute-1)', marginTop:3 }}>{it.tag}</div>}
              </>
            )}
            {active && (
              <div style={{ position:'absolute', top:8, right:8, width:18, height:18, borderRadius:99, background:T.ring, display:'flex', alignItems:'center', justifyContent:'center' }}>
                <IconCheck size={11} stroke="#fff" sw={3}/>
              </div>
            )}
          </button>
        );
      })}
    </div>
  );
}

/* =========== SEGMENTED CONTROL =========== */
function OSSegmented({ items, value, onChange, tone='lilac' }) {
  const T = OS_TONES[tone];
  return (
    <div style={{ display:'inline-flex', padding:3, background:'var(--paper-3)', borderRadius:99, border:'1px solid var(--line-2)' }}>
      {items.map(it => {
        const id = it.id || it;
        const active = value === id;
        return (
          <button key={id} onClick={()=>onChange(id)} type="button" style={{
            padding:'7px 16px', fontFamily:'var(--font-body)', fontWeight:600, fontSize:12.5,
            borderRadius:99, border:0,
            background: active ? 'var(--ink)' : 'transparent',
            color: active ? 'var(--chart-300)' : 'var(--mute-1)',
            cursor:'pointer', letterSpacing:'-0.005em',
          }}>{it.label || it}</button>
        );
      })}
    </div>
  );
}

/* =========== SECTION HEADING =========== */
function OSSection({ kicker, title, sub, children, num }) {
  return (
    <section style={{ marginTop:36 }}>
      {kicker && <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:9 }}>
        {num && <span style={{ fontFamily:'var(--font-mono)', fontSize:11, color:'var(--lilac-700)', fontWeight:600 }}>{num}</span>}
        <span className="eyebrow" style={{ color:'var(--mute-1)' }}>{kicker}</span>
      </div>}
      <h2 style={{ fontFamily:'var(--font-display)', fontSize:30, fontWeight:500, letterSpacing:'-0.035em', lineHeight:1.05, color:'var(--ink)', margin:0 }}>{title}</h2>
      {sub && <p style={{ fontSize:15, color:'var(--mute-1)', lineHeight:1.55, marginTop:10, maxWidth:740 }}>{sub}</p>}
      <div style={{ marginTop:20 }}>{children}</div>
    </section>
  );
}

/* =========== ROW TOGGLE =========== */
function OSToggleRow({ title, desc, value, onChange, badge, tone='lilac', meta, agent }) {
  const T = OS_TONES[tone];
  return (
    <div style={{
      display:'flex', alignItems:'center', justifyContent:'space-between', gap:18,
      padding:'14px 16px',
      background: value ? T.bgSoft : 'var(--paper)',
      border:'1px solid', borderColor: value ? T.ring : 'var(--line)',
      borderRadius:12, transition:'all .15s ease',
    }}>
      <div style={{ minWidth:0, flex:1 }}>
        <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap' }}>
          <span style={{ fontSize:14, fontWeight:600, color:'var(--ink)' }}>{title}</span>
          {agent && <span style={{ fontFamily:'var(--font-mono)', fontSize:10.5, color:T.fg, background:T.bg, padding:'1.5px 7px', borderRadius:99, fontWeight:600 }}>{agent}</span>}
          {badge && <span style={{ fontSize:10, fontWeight:700, letterSpacing:'0.08em', textTransform:'uppercase', color:'var(--lilac-700)', background:'var(--lilac-100)', padding:'2px 7px', borderRadius:99 }}>{badge}</span>}
        </div>
        {desc && <div style={{ fontSize:12.5, color:'var(--mute-1)', marginTop:3, lineHeight:1.4 }}>{desc}</div>}
        {meta && <div style={{ fontSize:11, color:'var(--mute-2)', marginTop:5, fontFamily:'var(--font-mono)' }}>{meta}</div>}
      </div>
      <OSSwitch value={value} onChange={onChange} tone={tone}/>
    </div>
  );
}

/* =========== SWITCH =========== */
function OSSwitch({ value, onChange, tone='lilac' }) {
  const T = OS_TONES[tone];
  return (
    <button onClick={()=>onChange(!value)} type="button" style={{
      width:38, height:22, borderRadius:99,
      background: value ? T.ring : 'var(--paper-3)',
      border:'1px solid', borderColor: value ? T.ring : 'var(--line)',
      position:'relative', cursor:'pointer', flexShrink:0, transition:'all .15s ease',
    }}>
      <span style={{
        position:'absolute', top:1, left: value ? 17 : 1,
        width:18, height:18, borderRadius:99, background:'#fff',
        boxShadow:'0 1px 2px rgba(0,0,0,.2)', transition:'left .15s ease',
      }}/>
    </button>
  );
}

/* =========== SLIDER =========== */
function OSSlider({ value, onChange, min=0, max=100, step=1, suffix='', tone='lilac', label }) {
  const T = OS_TONES[tone];
  const pct = ((value - min) / (max - min)) * 100;
  return (
    <div style={{ width:'100%' }}>
      {label && <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline', marginBottom:6 }}>
        <span style={{ fontSize:13, color:'var(--ink)', fontWeight:500 }}>{label}</span>
        <span style={{ fontFamily:'var(--font-mono)', fontSize:13, color:T.fg, fontWeight:600 }}>{value}{suffix}</span>
      </div>}
      <input type="range" min={min} max={max} step={step} value={value} onChange={e=>onChange(Number(e.target.value))}
        style={{
          width:'100%', WebkitAppearance:'none', appearance:'none', height:6,
          background:`linear-gradient(to right, ${T.ring} 0%, ${T.ring} ${pct}%, var(--paper-3) ${pct}%, var(--paper-3) 100%)`,
          borderRadius:99, outline:'none', cursor:'pointer',
        }}
      />
      <style>{`
        input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:18px; height:18px; border-radius:99px; background:var(--ink); border:2px solid var(--paper); box-shadow:0 1px 3px rgba(0,0,0,.25); cursor:pointer; }
        input[type=range]::-moz-range-thumb { width:18px; height:18px; border-radius:99px; background:var(--ink); border:2px solid var(--paper); cursor:pointer; }
      `}</style>
    </div>
  );
}

/* =========== MIX SLIDERS (sum to 100) =========== */
function OSMixSliders({ items, values, onChange, tone='chart' }) {
  const T = OS_TONES[tone];
  const total = items.reduce((s, it) => s + (values[it.id] ?? it.def), 0);
  return (
    <div style={{ display:'grid', gridTemplateColumns:'1fr', gap:14 }}>
      {items.map(it => {
        const v = values[it.id] ?? it.def;
        return (
          <div key={it.id} style={{ display:'grid', gridTemplateColumns:'200px 1fr 56px', alignItems:'center', gap:14 }}>
            <span style={{ fontSize:13, color:'var(--ink)', fontWeight:500 }}>{it.label}</span>
            <OSSlider value={v} onChange={nv=>onChange({ ...values, [it.id]: nv })} min={0} max={100} tone={tone}/>
            <span style={{ fontFamily:'var(--font-mono)', fontSize:13, color:T.fg, fontWeight:600, textAlign:'right' }}>{v}%</span>
          </div>
        );
      })}
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginTop:6, paddingTop:12, borderTop:'1px solid var(--line-2)' }}>
        <span style={{ fontSize:12, color:'var(--mute-1)', textTransform:'uppercase', letterSpacing:'0.1em', fontWeight:600 }}>Total mix</span>
        <span style={{ fontFamily:'var(--font-mono)', fontSize:15, fontWeight:700, color: total === 100 ? T.fg : '#c04040' }}>{total}% {total !== 100 && <span style={{ fontSize:11, marginLeft:4 }}>(should be 100)</span>}</span>
      </div>
    </div>
  );
}

/* =========== DRAG-TO-RANK LIST =========== */
function OSRankList({ items, value, onChange, max=5, tone='lilac' }) {
  // value is array of ranked ids. items has {id,label}.
  const T = OS_TONES[tone];
  const ranked = value || [];
  const move = (id, dir) => {
    const idx = ranked.indexOf(id);
    if (idx === -1) {
      if (ranked.length < items.length) onChange([...ranked, id]);
      return;
    }
    const next = [...ranked];
    const swap = idx + dir;
    if (swap < 0 || swap >= next.length) return;
    [next[idx], next[swap]] = [next[swap], next[idx]];
    onChange(next);
  };
  const remove = (id) => onChange(ranked.filter(r => r !== id));

  return (
    <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:18 }}>
      {/* ranked column */}
      <div>
        <div className="eyebrow" style={{ color:'var(--lilac-700)', marginBottom:8 }}>Your top {max} · ranked</div>
        <div style={{ display:'grid', gap:6, minHeight:80 }}>
          {ranked.length === 0 && <div style={{ padding:24, border:'1.5px dashed var(--line)', borderRadius:12, color:'var(--mute-2)', fontSize:13, textAlign:'center' }}>Click items on the right to rank them.</div>}
          {ranked.map((id, i) => {
            const item = items.find(it => it.id === id);
            const isTop = i < max;
            return (
              <div key={id} style={{
                display:'flex', alignItems:'center', gap:10, padding:'10px 12px',
                background: isTop ? T.bg : 'var(--paper-3)',
                border:'1px solid', borderColor: isTop ? T.ring : 'var(--line)',
                borderRadius:10,
              }}>
                <span style={{ fontFamily:'var(--font-mono)', fontSize:13, fontWeight:700, color: isTop ? T.fg : 'var(--mute-2)', minWidth:18 }}>#{i+1}</span>
                <span style={{ fontSize:13, color:'var(--ink)', flex:1 }}>{item?.label}</span>
                <button onClick={()=>move(id,-1)} disabled={i===0} type="button" style={{ background:'transparent', border:0, padding:4, cursor:i===0?'default':'pointer', color: i===0?'var(--mute-3)':'var(--ink)' }}>↑</button>
                <button onClick={()=>move(id,1)} disabled={i===ranked.length-1} type="button" style={{ background:'transparent', border:0, padding:4, cursor:i===ranked.length-1?'default':'pointer', color: i===ranked.length-1?'var(--mute-3)':'var(--ink)' }}>↓</button>
                <button onClick={()=>remove(id)} type="button" style={{ background:'transparent', border:0, padding:4, cursor:'pointer', color:'var(--mute-1)', fontSize:14 }}>✕</button>
              </div>
            );
          })}
        </div>
      </div>
      {/* available column */}
      <div>
        <div className="eyebrow" style={{ color:'var(--mute-1)', marginBottom:8 }}>All options</div>
        <div style={{ display:'grid', gap:5, maxHeight:430, overflowY:'auto', paddingRight:4 }}>
          {items.filter(it => !ranked.includes(it.id)).map(it => (
            <button key={it.id} type="button" onClick={()=>onChange([...ranked, it.id])} style={{
              textAlign:'left', padding:'9px 12px',
              background:'var(--paper)', border:'1px solid var(--line)', borderRadius:9,
              fontFamily:'var(--font-body)', fontSize:13, color:'var(--ink)', cursor:'pointer',
            }}>+ {it.label}</button>
          ))}
        </div>
      </div>
    </div>
  );
}

/* =========== STAT TILE =========== */
function OSStat({ label, value, sub, tone='chart' }) {
  const T = OS_TONES[tone];
  return (
    <div style={{ padding:'14px 16px', background:'var(--paper)', border:'1px solid var(--line)', borderRadius:12 }}>
      <div style={{ fontSize:10, fontWeight:700, letterSpacing:'0.12em', textTransform:'uppercase', color:'var(--mute-1)' }}>{label}</div>
      <div style={{ fontFamily:'var(--font-display)', fontSize:28, fontWeight:500, color:'var(--ink)', letterSpacing:'-0.025em', marginTop:4, lineHeight:1 }}>{value}</div>
      {sub && <div style={{ fontSize:11.5, color:T.fg, marginTop:4, fontWeight:500 }}>{sub}</div>}
    </div>
  );
}

/* =========== INPUT FIELD =========== */
function OSField({ label, value, onChange, placeholder, suffix, type='text', mono }) {
  return (
    <label style={{ display:'block' }}>
      {label && <div style={{ fontSize:12, fontWeight:600, color:'var(--mute-1)', textTransform:'uppercase', letterSpacing:'0.08em', marginBottom:6 }}>{label}</div>}
      <div style={{ display:'flex', alignItems:'stretch', background:'var(--paper)', border:'1px solid var(--line)', borderRadius:10 }}>
        <input type={type} value={value || ''} onChange={e=>onChange(e.target.value)} placeholder={placeholder} style={{
          flex:1, padding:'11px 13px', border:0, outline:'none', borderRadius:10,
          fontFamily: mono ? 'var(--font-mono)' : 'var(--font-body)',
          fontSize:14, color:'var(--ink)', background:'transparent',
        }}/>
        {suffix && <span style={{ display:'flex', alignItems:'center', padding:'0 14px', color:'var(--mute-1)', fontSize:13, fontFamily:'var(--font-mono)' }}>{suffix}</span>}
      </div>
    </label>
  );
}

/* =========== CONNECTION TILE =========== */
function OSConnectionTile({ conn, connected, onConnect }) {
  return (
    <div style={{
      padding:'16px', borderRadius:14,
      background: connected ? 'var(--chart-50)' : 'var(--paper)',
      border:'1px solid', borderColor: connected ? 'var(--chart-500)' : 'var(--line)',
      display:'flex', flexDirection:'column', gap:8,
      transition:'all .15s ease',
    }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <span style={{ fontSize:10, fontWeight:700, letterSpacing:'0.1em', textTransform:'uppercase', color: connected ? 'var(--chart-700)' : 'var(--mute-1)' }}>
          {conn.group}
        </span>
        {connected && <span style={{ display:'flex', alignItems:'center', gap:4, fontSize:11, color:'var(--chart-700)', fontWeight:600 }}>
          <span style={{ width:6, height:6, borderRadius:99, background:'var(--chart-500)' }} className="pulse-soft"/> live
        </span>}
      </div>
      <div style={{ fontSize:14, fontWeight:600, color:'var(--ink)' }}>{conn.name}</div>
      <div style={{ fontSize:12, color:'var(--mute-1)', lineHeight:1.45, flex:1 }}>{conn.tag}</div>
      <button onClick={()=>onConnect(!connected)} type="button" style={{
        marginTop:4, padding:'8px 12px', borderRadius:99,
        background: connected ? 'var(--paper)' : 'var(--ink)',
        color: connected ? 'var(--ink)' : 'var(--chart-300)',
        border: connected ? '1px solid var(--line)' : '0',
        fontFamily:'var(--font-body)', fontSize:12, fontWeight:600, cursor:'pointer',
      }}>{connected ? 'Connected · manage' : 'Connect →'}</button>
    </div>
  );
}

/* =========== PILL TAG (for chips, scrape targets) =========== */
function OSPill({ children, tone='lilac', active }) {
  const T = OS_TONES[tone];
  return (
    <span style={{
      display:'inline-flex', alignItems:'center', gap:6,
      padding:'4px 10px', borderRadius:99,
      background: active ? T.bg : 'var(--paper-3)',
      color: active ? T.fg : 'var(--ink)',
      fontSize:11.5, fontWeight:600,
      border:'1px solid', borderColor: active ? T.ring : 'var(--line-2)',
    }}>{children}</span>
  );
}

Object.assign(window, {
  OS_TONES, OSCardPicker, OSSegmented, OSSection, OSToggleRow, OSSwitch,
  OSSlider, OSMixSliders, OSRankList, OSStat, OSField, OSConnectionTile, OSPill,
});