// ===== Gemeinsame UI-Bausteine =====
const { useState, useRef, useEffect } = React;

// Dünne Line-Icons (stroke, round, currentColor)
function Icon({ name, size = 15, style }) {
  const c = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor',
    strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round', style };
  const P = {
    play:    <path d="M7 5l12 7-12 7V5z" />,
    sliders: <g><line x1="4" y1="7" x2="20" y2="7"/><line x1="4" y1="17" x2="20" y2="17"/><circle cx="9" cy="7" r="2.2"/><circle cx="15" cy="17" r="2.2"/></g>,
    settings:<g><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.2 4.2l2.1 2.1M17.7 17.7l2.1 2.1M2 12h3M19 12h3M4.2 19.8l2.1-2.1M17.7 6.3l2.1-2.1"/></g>,
    lock:    <g><rect x="5" y="11" width="14" height="9" rx="1.5"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></g>,
    layers:  <g><path d="M12 3l9 5-9 5-9-5 9-5z"/><path d="M3 13l9 5 9-5"/></g>,
    truck:   <g><path d="M3 6h11v9H3z"/><path d="M14 9h4l3 3v3h-7z"/><circle cx="7" cy="18" r="1.6"/><circle cx="17.5" cy="18" r="1.6"/></g>,
    box:     <g><path d="M3 8l9-5 9 5v8l-9 5-9-5V8z"/><path d="M3 8l9 5 9-5M12 13v8"/></g>,
    pin:     <g><path d="M12 21s7-6.3 7-11a7 7 0 1 0-14 0c0 4.7 7 11 7 11z"/><circle cx="12" cy="10" r="2.3"/></g>,
    close:   <g><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></g>,
    chevron: <path d="M9 6l6 6-6 6" />,
    plus:    <g><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></g>,
    check:   <path d="M5 12.5l4.5 4.5L19 7" />,
    arrow:   <g><line x1="4" y1="12" x2="20" y2="12"/><path d="M14 6l6 6-6 6"/></g>,
    alert:   <g><path d="M12 3l9.5 17H2.5L12 3z"/><line x1="12" y1="10" x2="12" y2="14"/><circle cx="12" cy="17" r=".4" fill="currentColor"/></g>,
    flag:    <g><line x1="6" y1="3" x2="6" y2="21"/><path d="M6 4h11l-2.2 3.5L17 11H6z"/></g>,
    grid:    <g><rect x="4" y="4" width="7" height="7" rx="1"/><rect x="13" y="4" width="7" height="7" rx="1"/><rect x="4" y="13" width="7" height="7" rx="1"/><rect x="13" y="13" width="7" height="7" rx="1"/></g>,
    calendar:<g><rect x="4" y="5" width="16" height="15" rx="2"/><line x1="4" y1="9.5" x2="20" y2="9.5"/><line x1="8" y1="3" x2="8" y2="6"/><line x1="16" y1="3" x2="16" y2="6"/></g>,
    target:  <g><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="4"/><circle cx="12" cy="12" r="0.6" fill="currentColor"/></g>,
    clock:   <g><circle cx="12" cy="12" r="8.5"/><path d="M12 7v5l3.5 2"/></g>,
    info:    <g><circle cx="12" cy="12" r="9"/><line x1="12" y1="11" x2="12" y2="16.5"/><circle cx="12" cy="7.8" r="0.7" fill="currentColor"/></g>,
    reset:   <g><path d="M3.5 12a8.5 8.5 0 1 0 2.6-6.1"/><path d="M3 4v4h4"/></g>,
    scissors:<g><circle cx="6" cy="6" r="2.4"/><circle cx="6" cy="18" r="2.4"/><line x1="8" y1="7.6" x2="20" y2="16"/><line x1="8" y1="16.4" x2="20" y2="8"/></g>,
    undo:    <g><path d="M4 9h11a5 5 0 0 1 0 10H9"/><path d="M8 5L4 9l4 4"/></g>,
    calc:    <g><rect x="5" y="3" width="14" height="18" rx="2"/><line x1="8" y1="7" x2="16" y2="7"/><line x1="8" y1="11" x2="8" y2="11"/><line x1="12" y1="11" x2="12" y2="11"/><line x1="16" y1="11" x2="16" y2="11"/><line x1="8" y1="15" x2="8" y2="15"/><line x1="12" y1="15" x2="12" y2="15"/><line x1="16" y1="15" x2="16" y2="17"/></g>,
  };
  return <svg {...c}>{P[name]}</svg>;
}

function L({ children, style }) {
  return <span className="label" style={style}>{children}</span>;
}

// Score-Badge: 1..9, Farbintensität nach Höhe
function ScoreBadge({ value, size = 'md', dim }) {
  const t = (value - 1) / 8;
  // Tint von neutral -> Akzentblau bei hohem Score
  const bg = `color-mix(in oklch, var(--accent) ${20 + t * 80}%, var(--surface))`;
  const bd = `color-mix(in oklch, var(--accent-line) ${30 + t * 70}%, var(--line))`;
  const px = size === 'sm' ? { w: 22, h: 20, f: 12 } : size === 'lg' ? { w: 30, h: 28, f: 15 } : { w: 26, h: 23, f: 13 };
  return (
    <span className="num" style={{
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      width: px.w, height: px.h, fontSize: px.f, fontWeight: 600,
      borderRadius: 5, background: bg, border: `1px solid ${bd}`,
      color: 'var(--accent-ink)', fontVariantNumeric: 'tabular-nums',
      opacity: dim ? 0.5 : 1, fontFamily: 'var(--mono)',
    }}>{value}</span>
  );
}

const BESTAND = {
  direkt:   { t: 'Direktbestand',   icon: 'box',   c: 'var(--good-ink)',  bg: 'var(--good)' },
  indirekt: { t: 'Indirekt',        icon: 'layers', c: 'var(--warn-ink)', bg: 'var(--warn)' },
  route:    { t: 'In Route',        icon: 'truck', c: 'var(--accent-ink)', bg: 'var(--accent)' },
};
function StatusPill({ kind }) {
  const s = BESTAND[kind] || BESTAND.route;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 7px 2px 6px',
      borderRadius: 99, fontSize: 11, fontWeight: 500,
      background: `color-mix(in oklch, ${s.bg} 55%, var(--surface))`,
      color: s.c, border: `1px solid color-mix(in oklch, ${s.bg} 70%, var(--line))` }}>
      <Icon name={s.icon} size={11} /> {s.t}
    </span>
  );
}

function MatChip({ mat, showName }) {
  const m = window.MATERIALS[mat];
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, whiteSpace: 'nowrap' }}>
      <span style={{ width: 9, height: 9, borderRadius: 2, background: m.color, flex: '0 0 auto', boxShadow: 'inset 0 0 0 1px rgba(0,0,0,.08)' }} />
      <span className="num" style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-2)' }}>{m.id}</span>
      {showName && <span style={{ color: 'var(--muted)' }}>{m.name}</span>}
    </span>
  );
}

// Stufenregler 0/1..9
function StepRange({ value, onChange, min = 0, max = 9 }) {
  return (
    <div style={{ display: 'flex', gap: 3 }}>
      {Array.from({ length: max - min + 1 }, (_, i) => i + min).map(n => {
        const on = n !== 0 && n <= value;
        const isZero = n === 0;
        return (
          <button key={n} onClick={() => onChange(n)} title={isZero ? 'ignorieren' : String(n)}
            style={{
              width: 20, height: 26, border: '1px solid', borderRadius: 4, padding: 0,
              fontFamily: 'var(--mono)', fontSize: 11, fontWeight: 600,
              borderColor: value === n ? 'var(--accent-ink)' : (on ? 'var(--accent-line)' : 'var(--line-2)'),
              background: isZero ? (value === 0 ? 'var(--line-2)' : 'var(--surface)')
                : on ? `color-mix(in oklch, var(--accent) ${30 + (n/9)*70}%, var(--surface))` : 'var(--surface)',
              color: isZero ? 'var(--muted)' : on ? 'var(--accent-ink)' : 'var(--muted)',
              cursor: 'pointer', transition: 'all .12s',
            }}>{isZero ? '–' : n}</button>
        );
      })}
    </div>
  );
}

// Schieberegler (Optimierungsziel)
function Slider({ value, onChange, accent = 'var(--accent-ink)' }) {
  return (
    <input type="range" min="0" max="100" value={value}
      onChange={e => onChange(+e.target.value)}
      style={{ width: '100%', height: 22, cursor: 'pointer', accentColor: accent }} />
  );
}

function IconBtn({ icon, label, onClick, active, primary, disabled }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      display: 'inline-flex', alignItems: 'center', gap: 7, height: 32, padding: '0 12px',
      borderRadius: 6, fontSize: 12.5, fontWeight: 500,
      border: '1px solid', transition: 'all .14s',
      borderColor: primary ? 'var(--accent-ink)' : active ? 'var(--accent-line)' : 'var(--line-2)',
      background: primary ? 'var(--accent-ink)' : active ? 'var(--accent)' : 'var(--surface)',
      color: primary ? '#fff' : 'var(--ink)',
      boxShadow: primary ? '0 1px 2px rgba(47,78,120,.25)' : 'none',
      opacity: disabled ? 0.4 : 1, cursor: disabled ? 'not-allowed' : 'pointer',
    }}>
      {icon && <Icon name={icon} size={15} />}{label}
    </button>
  );
}

// ===== Sortierung für Tabellen =====
function useSort(defaultKey = null, defaultDir = 1) {
  const [sort, setSort] = useState({ key: defaultKey, dir: defaultDir });
  const toggle = (key) => setSort(s =>
    s.key === key ? (s.dir === 1 ? { key, dir: -1 } : { key: null, dir: 1 }) : { key, dir: 1 });
  return [sort, toggle];
}
function sortRows(arr, sort, accessor) {
  if (!sort.key) return arr;
  const a = [...arr];
  a.sort((x, y) => {
    let vx = accessor(x, sort.key), vy = accessor(y, sort.key);
    if (vx == null) vx = ''; if (vy == null) vy = '';
    if (typeof vx === 'string' && typeof vy === 'string') return vx.localeCompare(vy) * sort.dir;
    return (vx < vy ? -1 : vx > vy ? 1 : 0) * sort.dir;
  });
  return a;
}
// Sortierbarer Tabellenkopf
function SortTh({ label, sortKey, sort, onSort, align = 'left', style }) {
  const active = sort.key === sortKey;
  return (
    <th onClick={() => onSort(sortKey)}
      style={{ ...window.thStyle, textAlign: align, cursor: 'pointer', userSelect: 'none',
        color: active ? 'var(--accent-ink)' : 'var(--muted)', whiteSpace: 'nowrap', ...style }}>
      <span style={{ display: 'inline-flex', alignItems: 'center', gap: 3, flexDirection: align === 'right' ? 'row-reverse' : 'row' }}>
        {label}
        <span style={{ display: 'inline-flex', width: 8, opacity: active ? 1 : 0.32 }}>
          {active ? (sort.dir === 1 ? '▲' : '▼') : '⇅'}
        </span>
      </span>
    </th>
  );
}

Object.assign(window, { Icon, L, ScoreBadge, StatusPill, MatChip, StepRange, Slider, IconBtn, useSort, sortRows, SortTh });
