// ===== KiKi — Kommentar-System (Rechtsklick auf Zeilen & Widgets) =====
const { useState: useKkS, useEffect: useKkE, useRef: useKkR } = React;

const KK_KEY = 'solver.comments';
const KK_CATS_KEY = 'solver.commentCats';
const KK_DEFAULT_CATS = ['Qualität', 'Termin', 'Rüsten', 'Material', 'Kapazität', 'Sonstiges'];

function kkLoad() { try { return JSON.parse(localStorage.getItem(KK_KEY) || '[]'); } catch (e) { return []; } }
function kkSave(list) { try { localStorage.setItem(KK_KEY, JSON.stringify(list)); } catch (e) {} }
function kkLoadCats() { try { const c = JSON.parse(localStorage.getItem(KK_CATS_KEY) || 'null'); return Array.isArray(c) && c.length ? c : KK_DEFAULT_CATS.slice(); } catch (e) { return KK_DEFAULT_CATS.slice(); } }
function kkSaveCats(c) { try { localStorage.setItem(KK_CATS_KEY, JSON.stringify(c)); } catch (e) {} }

// globaler, einfacher Store mit Subscriber-Benachrichtigung
const KkStore = {
  list: kkLoad(), cats: kkLoadCats(), subs: new Set(),
  sub(fn) { this.subs.add(fn); return () => this.subs.delete(fn); },
  emit() { this.subs.forEach(fn => fn()); },
  add(c) { this.list = [{ id: 'k' + Date.now() + Math.floor(Math.random() * 999), ts: new Date().toISOString(), ...c }, ...this.list]; kkSave(this.list); this.emit(); },
  remove(id) { this.list = this.list.filter(c => c.id !== id); kkSave(this.list); this.emit(); },
  addCat(name) { if (name && !this.cats.includes(name)) { this.cats = [...this.cats, name]; kkSaveCats(this.cats); this.emit(); } },
};

// von überall aufrufbar: Kontextmenü an Cursorposition öffnen
window.kikiMenu = (e, target) => {
  e.preventDefault(); e.stopPropagation();
  window.dispatchEvent(new CustomEvent('kiki:menu', { detail: { x: e.clientX, y: e.clientY, target } }));
};

// ── Layer: Kontextmenü + Dialog (einmal in App gemountet) ──
function KikiLayer() {
  const [menu, setMenu] = useKkS(null);   // {x,y,target}
  const [dialog, setDialog] = useKkS(null); // {target}
  useKkE(() => {
    const onMenu = (e) => setMenu(e.detail);
    window.addEventListener('kiki:menu', onMenu);
    const onClick = () => setMenu(null);
    window.addEventListener('click', onClick);
    return () => { window.removeEventListener('kiki:menu', onMenu); window.removeEventListener('click', onClick); };
  }, []);
  return (
    <React.Fragment>
      {menu && (
        <div style={{ position: 'fixed', left: Math.min(menu.x, window.innerWidth - 190), top: Math.min(menu.y, window.innerHeight - 90), zIndex: 80,
          background: 'var(--panel)', border: '1px solid var(--line-2)', borderRadius: 9, boxShadow: '0 12px 36px rgba(63,62,61,.22)', padding: 5, minWidth: 178, animation: 'rowIn .12s' }}
          onClick={e => e.stopPropagation()}>
          <div style={{ padding: '6px 10px 4px', fontSize: 10.5, color: 'var(--muted)', fontFamily: 'var(--mono)', textTransform: 'uppercase', letterSpacing: '.08em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{menu.target.label}</div>
          <button onClick={() => { setDialog({ target: menu.target }); setMenu(null); }} style={kkMenuItem}>
            <span style={{ display: 'grid', placeItems: 'center', width: 22, height: 22, borderRadius: 6, background: 'var(--accent)', color: 'var(--accent-ink)', fontWeight: 700, fontSize: 11, fontFamily: 'var(--mono)' }}>ki</span>
            kiki — Kommentar
          </button>
        </div>
      )}
      {dialog && <CommentDialog target={dialog.target} onClose={() => setDialog(null)} />}
    </React.Fragment>
  );
}
const kkMenuItem = { display: 'flex', alignItems: 'center', gap: 9, width: '100%', padding: '8px 10px', border: 'none', background: 'transparent', borderRadius: 6, cursor: 'pointer', fontSize: 13, fontWeight: 500, color: 'var(--ink)', textAlign: 'left' };

// ── Kommentar-Dialog (Slide-Over) mit Kategorien + Spracheingabe ──
function CommentDialog({ target, onClose }) {
  const cats = KkStore.cats;
  const [cat, setCat] = useKkS(cats[0]);
  const [text, setText] = useKkS('');
  const [newCat, setNewCat] = useKkS('');
  const [addingCat, setAddingCat] = useKkS(false);
  const [listening, setListening] = useKkS(false);
  const [err, setErr] = useKkS(null);
  const recRef = useKkR(null);
  const taRef = useKkR(null);

  const toggleVoice = () => {
    const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (!SR) { setErr('Spracheingabe wird vom Browser nicht unterstützt'); return; }
    if (listening) { recRef.current && recRef.current.stop(); setListening(false); return; }
    const rec = new SR(); rec.lang = 'de-DE'; rec.continuous = true; rec.interimResults = true;
    let base = text ? text + ' ' : '';
    rec.onresult = (ev) => {
      let s = '';
      for (let i = ev.resultIndex; i < ev.results.length; i++) s += ev.results[i][0].transcript;
      setText(base + s);
    };
    rec.onerror = (ev) => { setErr('Sprachfehler: ' + ev.error); setListening(false); };
    rec.onend = () => setListening(false);
    recRef.current = rec; rec.start(); setListening(true); setErr(null);
  };

  const save = () => {
    if (!text.trim()) { setErr('Bitte einen Kommentar eingeben'); return; }
    if (recRef.current) recRef.current.stop();
    KkStore.add({ refId: target.id, refLabel: target.label, kind: target.kind || 'Auftrag', cat, text: text.trim() });
    onClose();
  };

  return (
    <React.Fragment>
      <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(63,62,61,.3)', zIndex: 81, animation: 'rowIn .15s' }} />
      <div style={{ position: 'fixed', top: 0, right: 0, bottom: 0, width: 420, background: 'var(--surface)', zIndex: 82, boxShadow: '-12px 0 40px rgba(63,62,61,.18)', borderLeft: '1px solid var(--line-2)', display: 'flex', flexDirection: 'column', animation: 'kkSlide .26s cubic-bezier(.2,.8,.2,1)' }}>
        <style>{`@keyframes kkSlide{from{transform:translateX(100%)}to{transform:none}}`}</style>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '15px 18px', borderBottom: '1px solid var(--line)' }}>
          <span style={{ display: 'grid', placeItems: 'center', width: 28, height: 28, borderRadius: 7, background: 'var(--accent-ink)', color: '#fff', fontWeight: 700, fontSize: 13, fontFamily: 'var(--mono)' }}>ki</span>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 600, fontSize: 14.5 }}>kiki — Kommentar</div>
            <div className="num" style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{target.label}</div>
          </div>
          <button onClick={onClose} style={{ marginLeft: 'auto', width: 30, height: 30, border: '1px solid var(--line-2)', borderRadius: 6, background: 'var(--surface)', display: 'grid', placeItems: 'center', color: 'var(--ink-2)', cursor: 'pointer' }}><Icon name="close" size={15} /></button>
        </div>

        <div style={{ flex: 1, overflow: 'auto', padding: '16px 18px' }}>
          {/* Kategorie */}
          <div className="label" style={{ marginBottom: 8 }}>Kategorie</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
            {cats.map(c => (
              <button key={c} onClick={() => setCat(c)} style={{ height: 30, padding: '0 12px', borderRadius: 99, fontSize: 12.5, fontWeight: 500, cursor: 'pointer',
                border: '1px solid ' + (cat === c ? 'var(--accent-ink)' : 'var(--line-2)'), background: cat === c ? 'var(--accent)' : 'var(--surface)', color: cat === c ? 'var(--accent-ink)' : 'var(--ink-2)' }}>{c}</button>
            ))}
            {addingCat ? (
              <span style={{ display: 'inline-flex', gap: 4 }}>
                <input autoFocus value={newCat} onChange={e => setNewCat(e.target.value)} onKeyDown={e => { if (e.key === 'Enter' && newCat.trim()) { KkStore.addCat(newCat.trim()); setCat(newCat.trim()); setNewCat(''); setAddingCat(false); } }}
                  placeholder="Neue Kategorie" style={{ height: 30, padding: '0 10px', borderRadius: 99, border: '1px solid var(--accent-line)', fontSize: 12.5, width: 130, background: 'var(--surface)', color: 'var(--ink)' }} />
                <button onClick={() => { if (newCat.trim()) { KkStore.addCat(newCat.trim()); setCat(newCat.trim()); } setNewCat(''); setAddingCat(false); }} style={{ height: 30, width: 30, borderRadius: 99, border: 'none', background: 'var(--accent-ink)', color: '#fff', cursor: 'pointer', display: 'grid', placeItems: 'center' }}><Icon name="check" size={14} /></button>
              </span>
            ) : (
              <button onClick={() => setAddingCat(true)} title="Kategorie hinzufügen" style={{ height: 30, padding: '0 11px', borderRadius: 99, border: '1px dashed var(--line-2)', background: 'transparent', color: 'var(--ink-2)', cursor: 'pointer', fontSize: 12.5, display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="plus" size={13} /> Kategorie</button>
            )}
          </div>

          {/* Kommentar + Spracheingabe */}
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', margin: '14px 0 8px' }}>
            <span className="label">Kommentar</span>
            <button onClick={toggleVoice} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, height: 30, padding: '0 12px', borderRadius: 99, cursor: 'pointer', fontSize: 12, fontWeight: 600,
              border: '1px solid ' + (listening ? 'var(--bad-ink)' : 'var(--accent-line)'), background: listening ? 'color-mix(in oklch, var(--bad) 20%, var(--surface))' : 'var(--surface)', color: listening ? 'var(--bad-ink)' : 'var(--accent-ink)' }}>
              <Icon name="mic" size={14} /> {listening ? 'Aufnahme läuft… stoppen' : 'Spracheingabe'}
            </button>
          </div>
          <textarea ref={taRef} value={text} onChange={e => setText(e.target.value)} placeholder="Kommentar eingeben oder diktieren…"
            style={{ width: '100%', minHeight: 150, boxSizing: 'border-box', padding: 12, borderRadius: 8, border: '1px solid var(--line-2)', fontSize: 13.5, fontFamily: 'var(--sans)', lineHeight: 1.5, resize: 'vertical', background: 'var(--surface)', color: 'var(--ink)' }} />
          {listening && <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, marginTop: 8, fontSize: 12, color: 'var(--bad-ink)' }}><span style={{ width: 8, height: 8, borderRadius: 99, background: 'var(--bad-ink)', animation: 'pulseLine 1s infinite' }} /> hört zu…</div>}
          {err && <div style={{ marginTop: 8, fontSize: 12, color: 'var(--bad-ink)' }}>{err}</div>}
        </div>

        <div style={{ display: 'flex', gap: 8, padding: '14px 18px', borderTop: '1px solid var(--line)' }}>
          <button onClick={onClose} style={{ flex: 1, height: 38, borderRadius: 8, border: '1px solid var(--line-2)', background: 'var(--surface)', color: 'var(--ink-2)', fontWeight: 500, fontSize: 13, cursor: 'pointer' }}>Abbrechen</button>
          <button onClick={save} style={{ flex: 1, height: 38, borderRadius: 8, border: 'none', background: '#3269B4', color: '#fff', fontWeight: 600, fontSize: 13, cursor: 'pointer' }}>Speichern</button>
        </div>
      </div>
    </React.Fragment>
  );
}

Object.assign(window, { KikiLayer, KkStore });

// ── KiKi Assistent: Floating-Button + Chat-Panel (rechts) ──
function KikiAssistant() {
  const [open, setOpen] = useKkS(false);
  const [msgs, setMsgs] = useKkS([{ role: 'ki', text: 'Hallo! Ich bin KiKi, dein KI-Assistent für Planung & Shopfloor. Frag mich nach Auswertungen, Kommentaren oder Auffälligkeiten — z. B. „Fasse die offenen Maßnahmen zusammen" oder „Wo ist die Termintreue kritisch?"' }]);
  const [input, setInput] = useKkS('');
  const [busy, setBusy] = useKkS(false);
  const scrollRef = useKkR(null);
  useKkE(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [msgs, busy]);
  useKkE(() => { const onOpen = () => setOpen(true); window.addEventListener('kiki:open', onOpen); return () => window.removeEventListener('kiki:open', onOpen); }, []);

  const suggestions = [
    'Fasse die offenen Maßnahmen zusammen',
    'Wo ist die Termintreue kritisch?',
    'Werte die Kommentare aus',
    'Welche Aufträge sind verspätet?',
  ];

  const answer = (qRaw) => {
    const q = qRaw.toLowerCase();
    const orders = window.A_ORDERS || [];
    const done = orders.filter(o => o.istEnde);
    const late = done.filter(o => o.taAbgang > 0);
    const measures = (window.SfStore ? window.SfStore.list : []);
    const openM = measures.filter(m => m.status !== 'erledigt');
    const comments = (window.KkStore ? window.KkStore.list : []);

    if (/maßnahme|massnahme|shopfloor|offen/.test(q)) {
      const byCat = {};
      openM.forEach(m => { byCat[m.cat] = (byCat[m.cat] || 0) + 1; });
      const overdue = openM.filter(m => m.due < '2026-07-17');
      return { text: `Aktuell **${openM.length} offene Maßnahmen**:\n${Object.entries(byCat).map(([c, n]) => `· ${c}: ${n}`).join('\n')}\n\n${overdue.length ? `⚠️ **${overdue.length} überfällig**, u. a. „${overdue[0].titel}" (${overdue[0].owner}).` : 'Keine überfällig.'}\n\nEmpfehlung: die überfälligen zuerst eskalieren und Verantwortliche im nächsten Team-Meeting ansprechen.` };
    }
    if (/termintreu|verspät|verspaet|kritisch|liefer/.test(q)) {
      const pct = done.length ? Math.round((done.length - late.length) / done.length * 100) : 0;
      const bySys = {}; late.forEach(o => { bySys[o.system] = (bySys[o.system] || 0) + 1; });
      const worst = Object.entries(bySys).sort((a, b) => b[1] - a[1])[0];
      return { text: `**Termintreue gesamt: ${pct}%** (${late.length} von ${done.length} verspätet).\n\n${worst ? `Kritischstes System: **${worst[0]}** mit ${worst[1]} verspäteten Aufträgen.` : ''}\n\nTypische Ursache in den Daten: hohe Rüstanteile und Zulaufverzug. Vorschlag: Rüstoptimierung im Solver stärker gewichten und Übergangszeiten prüfen.` };
    }
    if (/kommentar/.test(q)) {
      if (!comments.length) return { text: 'Es sind noch keine KiKi-Kommentare erfasst. Rechtsklick auf eine Zeile oder ein Widget → „kiki", dann erscheinen sie hier in der Auswertung.' };
      const byCat = {}; comments.forEach(c => { byCat[c.cat] = (byCat[c.cat] || 0) + 1; });
      const top = Object.entries(byCat).sort((a, b) => b[1] - a[1]);
      return { text: `**${comments.length} Kommentare** erfasst, Schwerpunkte:\n${top.map(([c, n]) => `· ${c}: ${n}`).join('\n')}\n\nJüngster: „${comments[0].text.slice(0, 80)}" — Bezug ${comments[0].refLabel || comments[0].refId}.\n\nStimmungsbild: die Häufung bei „${top[0][0]}" deutet auf einen wiederkehrenden Engpass hin — lohnt eine Ursachenanalyse.` };
    }
    if (/verspätet|welche auftr|rückstand|ruckstand/.test(q)) {
      const list = late.slice(0, 5).map(o => `· ${o.nr} ${o.bez} (+${o.taAbgang} T, ${o.system})`).join('\n');
      return { text: `**${late.length} verspätete Aufträge.** Top nach Verzug:\n${list || 'keine'}\n\nSammelmaßnahme? Ich kann daraus eine Shopfloor-Maßnahme „Rückstand aufholen" vorbereiten.` };
    }
    if (/oee|auslastung|engpass|kapazit/.test(q)) {
      return { text: 'Die OEE-Abweichung zeigt CTX 4 rund 6 Punkte unter Ziel — Haupttreiber sind Rüstzeiten. Kapazitätsseitig ist das Fräszentrum das Nadelöhr mit der höchsten Reichweite. Vorschlag: Rüstmatrix pflegen und Überstunden gezielt am Fräszentrum einplanen.' };
    }
    return { text: 'Ich werte Aufträge, Arbeitssysteme, Shopfloor-Maßnahmen und Kommentare aus. Probier z. B.:\n· „Fasse die offenen Maßnahmen zusammen"\n· „Wo ist die Termintreue kritisch?"\n· „Werte die Kommentare aus"\n· „Welche Aufträge sind verspätet?"' };
  };

  const send = (text) => {
    const t = (text != null ? text : input).trim();
    if (!t || busy) return;
    setMsgs(m => [...m, { role: 'user', text: t }]);
    setInput(''); setBusy(true);
    setTimeout(() => { const a = answer(t); setMsgs(m => [...m, { role: 'ki', text: a.text }]); setBusy(false); }, 650);
  };

  const renderText = (txt) => txt.split('\n').map((ln, i) => {
    const parts = ln.split(/(\*\*[^*]+\*\*)/g).map((p, j) => p.startsWith('**') ? <b key={j} style={{ color: 'var(--ink)' }}>{p.slice(2, -2)}</b> : p);
    return <div key={i} style={{ minHeight: ln ? 0 : 8 }}>{parts}</div>;
  });

  return (
    <React.Fragment>
      {open && (
        <React.Fragment>
          <div onClick={() => setOpen(false)} style={{ position: 'fixed', inset: 0, background: 'rgba(63,62,61,.28)', zIndex: 90, animation: 'rowIn .15s' }} />
          <div style={{ position: 'fixed', top: 0, right: 0, bottom: 0, width: 420, maxWidth: '92vw', background: 'var(--surface)', zIndex: 91, boxShadow: '-12px 0 40px rgba(63,62,61,.2)', borderLeft: '1px solid var(--line-2)', display: 'flex', flexDirection: 'column', animation: 'kkSlide .26s cubic-bezier(.2,.8,.2,1)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '14px 16px', borderBottom: '1px solid var(--line)' }}>
              <span style={{ display: 'grid', placeItems: 'center', width: 30, height: 30, borderRadius: 8, background: '#3269B4', color: '#fff', fontWeight: 800, fontSize: 13, fontFamily: 'var(--mono)' }}>ki</span>
              <div><div style={{ fontWeight: 600, fontSize: 14.5 }}>KiKi</div><div style={{ fontSize: 11, color: 'var(--muted)' }}>KI-Assistent · Auswertung & Kommentare</div></div>
              <button onClick={() => setOpen(false)} style={{ marginLeft: 'auto', width: 30, height: 30, border: '1px solid var(--line-2)', borderRadius: 6, background: 'var(--surface)', display: 'grid', placeItems: 'center', color: 'var(--ink-2)', cursor: 'pointer' }}><Icon name="close" size={15} /></button>
            </div>

            <div ref={scrollRef} style={{ flex: 1, overflow: 'auto', padding: 16, display: 'flex', flexDirection: 'column', gap: 12 }}>
              {msgs.map((m, i) => (
                <div key={i} style={{ display: 'flex', justifyContent: m.role === 'user' ? 'flex-end' : 'flex-start' }}>
                  <div style={{ maxWidth: '86%', padding: '9px 12px', borderRadius: 12, fontSize: 13, lineHeight: 1.5,
                    background: m.role === 'user' ? 'var(--accent)' : 'var(--panel)', color: 'var(--ink)',
                    border: '1px solid ' + (m.role === 'user' ? 'var(--accent-line)' : 'var(--line)'),
                    borderBottomRightRadius: m.role === 'user' ? 3 : 12, borderBottomLeftRadius: m.role === 'user' ? 12 : 3 }}>
                    {renderText(m.text)}
                  </div>
                </div>
              ))}
              {busy && <div style={{ fontSize: 12, color: 'var(--muted)', display: 'inline-flex', alignItems: 'center', gap: 6 }}><span style={{ width: 8, height: 8, borderRadius: 99, background: '#3269B4', animation: 'pulseLine 1s infinite' }} /> KiKi analysiert…</div>}
              {msgs.length <= 1 && (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 4 }}>
                  {suggestions.map(s => <button key={s} onClick={() => send(s)} style={{ padding: '7px 11px', borderRadius: 99, border: '1px solid var(--accent-line)', background: 'var(--panel)', color: 'var(--accent-ink)', fontSize: 12, cursor: 'pointer', textAlign: 'left' }}>{s}</button>)}
                </div>
              )}
            </div>

            <div style={{ display: 'flex', gap: 8, padding: '12px 14px', borderTop: '1px solid var(--line)' }}>
              <input value={input} onChange={e => setInput(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') send(); }} placeholder="KiKi etwas fragen…"
                style={{ flex: 1, height: 38, boxSizing: 'border-box', padding: '0 12px', border: '1px solid var(--line-2)', borderRadius: 8, fontSize: 13, background: 'var(--panel)', color: 'var(--ink)' }} />
              <button onClick={() => send()} disabled={!input.trim() || busy} style={{ width: 44, height: 38, borderRadius: 8, border: 'none', background: '#3269B4', color: '#fff', cursor: input.trim() ? 'pointer' : 'not-allowed', opacity: input.trim() ? 1 : 0.5, display: 'grid', placeItems: 'center' }}><Icon name="arrow" size={16} /></button>
            </div>
          </div>
        </React.Fragment>
      )}
    </React.Fragment>
  );
}

Object.assign(window, { KikiAssistant });
