/* global React, Icon, BrandMark, SignalLineChart, MicroSpark, useStore, aiReply, aiPrompts */
const { useState, useRef, useEffect } = React;
const SEVC = { red: "var(--red)", amber: "var(--amber)", green: "var(--green)" };
const SEVW = { red: "критично", amber: "внимание", green: "рост" };
const ST = window.SignalStatus;

// Фокус-режимы (зелёная/красная — как просил владелец: Успехи / Отклонения)
const FOCUS = [
  { id: "deviations", label: "Отклонения", dot: "var(--red)", hint: "что чинить" },
  { id: "successes", label: "Успехи", dot: "var(--green)", hint: "что усиливать" },
  { id: "in_work", label: "В работе", dot: "var(--cyan)", hint: "взято в работу" },
  { id: "resolved", label: "Решённые", dot: "var(--text-3)", hint: "журнал решений" },
  { id: "all", label: "Все", dot: null, hint: "полный список" },
];

function feedFor(st, store) {
  const f = st.activeFocus;
  let list = st.signals.slice();
  if (f === "deviations") list = list.filter((s) => store.isOpen(s) && s.severity !== "green");
  else if (f === "successes") list = list.filter((s) => store.isOpen(s) && s.severity === "green");
  else if (f === "in_work") list = list.filter((s) => s.status === "in_work");
  else if (f === "resolved") list = list.filter((s) => store.isResolved(s));
  const ord = { new: 0, in_work: 1, closed: 2, rejected: 3 };
  const sev = { red: 0, amber: 1, green: 2 };
  return list.sort((a, b) => (ord[a.status] - ord[b.status]) || (sev[a.severity] - sev[b.severity]));
}

function StatusBadge({ s }) {
  const meta = ST[s.status];
  return (
    <span className="wa-status" style={{ color: meta.color, borderColor: `color-mix(in srgb, ${meta.color} 40%, transparent)` }}>
      {s.status === "in_work" ? <i className="pulse-dot" style={{ background: meta.color }} /> : null}
      {meta.label}{s.escalated && s.status === "in_work" ? " · эскалация" : ""}
    </span>
  );
}

function WebApp() {
  const store = useStore();
  const st = store.get();
  const [view, setView] = useState("feed");
  const [openId, setOpenId] = useState(null);
  const [onlyMine, setOnlyMine] = useState(false);
  const [onbOpen, setOnbOpen] = useState(() => { try { return localStorage.getItem("signal_onb_web") !== "0"; } catch { return true; } });

  const fc = store.focusCounts();
  const open = st.signals.find((s) => s.id === openId) || null;
  let feed = feedFor(st, store);
  if (onlyMine) feed = feed.filter((s) => s.role === st.activeRole);

  const kpis = [
    { foc: "deviations", lab: "Отклонения", val: fc.deviations, d: "требуют решения", flag: "red" },
    { foc: "successes", lab: "Успехи", val: fc.successes, d: "точки роста", flag: "green" },
    { foc: "in_work", lab: "В работе", val: fc.in_work, d: fc.escalated ? `${fc.escalated} на эскалации` : "под контролем", flag: "amber" },
    { foc: "resolved", lab: "Решено", val: fc.resolved, d: "с комментарием", flag: "" },
  ];

  function closeOnb() { setOnbOpen(false); try { localStorage.setItem("signal_onb_web", "0"); } catch {} }
  function focusTo(f) { store.setFocus(f); setView("feed"); }

  return (
    <div className="wa">
      <aside className="wa-side">
        <a className="wa-back" href="/demo"><span className="chev">←</span>Все приложения демо</a>
        <a className="wa-brand" href="/" title="На главную ai-control-center.ru"><span className="m"><BrandMark size={16} /></span><div><b>Сигнал</b><small>WEB · ПУЛЬТ</small></div></a>
        <div className="wa-sec">Рабочее место</div>
        <button className={`wa-nav ${view === "feed" ? "on" : ""}`} onClick={() => setView("feed")}><Icon name="signal" size={17} />Сигналы {fc.deviations ? <span className="ct red">{fc.deviations}</span> : null}</button>
        <button className={`wa-nav ${view === "metrics" ? "on" : ""}`} onClick={() => setView("metrics")}><Icon name="chart" size={17} />Показатели <span className="ct">{st.metrics.length}</span></button>
        <button className={`wa-nav ${view === "journal" ? "on" : ""}`} onClick={() => setView("journal")}><Icon name="check" size={17} />Журнал решений {fc.resolved ? <span className="ct">{fc.resolved}</span> : null}</button>
        <button className={`wa-nav ${view === "chat" ? "on" : ""}`} onClick={() => setView("chat")}><Icon name="brain" size={17} />AI советник</button>
        <div className="wa-sec">Данные</div>
        <button className="wa-nav"><Icon name="database" size={17} />Источники</button>
        <button className="wa-nav"><Icon name="layers" size={17} />Витрины</button>
        <div className="wa-side-foot">
          <button className="wa-clear" onClick={() => { if (confirm("Очистить все данные демо? Сигналы, статусы и журнал решений вернутся к исходным.")) store.clearData(); }}><Icon name="arrow" size={13} />Очистить данные</button>
          <div className="wa-foot"><span className="wa-av">СЦ</span><span className="nm">С. Цветков<small>{st.activeRole}</small></span></div>
        </div>
      </aside>

      <div className="wa-main">
        <header className="wa-top">
          <div><h1>{view === "feed" ? "Пульт управления" : view === "metrics" ? "Показатели" : view === "journal" ? "Журнал решений" : "AI советник"}</h1><div className="sub">{view === "metrics" ? "Генеральный директор · торговая компания" : view === "journal" ? "Что и как было решено по сигналам" : "Управление по сигналам · обновлено только что"}</div></div>
          <div className="wa-roles">
            {st.roles.map((r) => <button key={r} className={st.activeRole === r ? "on" : ""} onClick={() => store.setRole(r)}>{r}</button>)}
          </div>
          <button className="wa-ibtn" onClick={() => { store.clearNotifs(); setView("journal"); }} title="Уведомления"><Icon name="bell" size={17} />{st.notifications.filter((n)=>!n.read).length ? <span className="dot">{st.notifications.filter((n)=>!n.read).length}</span> : null}</button>
        </header>

        <div className="wa-canvas">
          {view === "feed" ? (
            <>
              {onbOpen ? (
                <div className="wa-onb">
                  <span className="wa-onb-ic"><Icon name="signal" size={18} /></span>
                  <div className="wa-onb-body">
                    <b>Это пульт управления по сигналам.</b> 🔴 <b>Отклонения</b> — что чинить, 🟢 <b>Успехи</b> — что усиливать. Откройте сигнал → <b>возьмите в работу</b>, сделайте шаг и <b>закройте с комментарием</b> «что сделано». Так в компании появляется дисциплина решений — и ничего не теряется.
                  </div>
                  <button className="wa-onb-x" onClick={closeOnb}>×</button>
                </div>
              ) : null}

              <div className="wa-kpis">
                {kpis.map((k) => (
                  <button className={`wa-kpi ${k.flag} ${st.activeFocus === k.foc ? "active" : ""}`} key={k.lab} onClick={() => focusTo(k.foc)}>
                    <span className="lab">{k.lab}</span><div className="val">{k.val}</div><div className="d">{k.d}</div>
                  </button>
                ))}
              </div>

              <div className="wa-filters">
                {FOCUS.map((f) => (
                  <button key={f.id} className={`wa-filt ${st.activeFocus === f.id ? "on" : ""}`} onClick={() => store.setFocus(f.id)} title={f.hint}>
                    {f.dot ? <i style={{ background: f.dot }} /> : null}{f.label}
                  </button>
                ))}
                <button className={`wa-filt mine ${onlyMine ? "on" : ""}`} onClick={() => setOnlyMine((v) => !v)}><Icon name="users" size={13} />Моя роль · {st.activeRole}</button>
                <span className="wa-filt-sp">{feed.length} сигналов</span>
              </div>

              <div className="wa-feed">
                {feed.map((s) => (
                  <div className={`wa-card ${s.status === "new" ? "unread" : ""} ${store.isResolved(s) ? "resolved" : ""}`} key={s.id} onClick={() => { setOpenId(s.id); store.markRead(s.id); }}>
                    <span className="wa-bar" style={{ background: SEVC[s.severity] }} />
                    <div>
                      <span className="ttl">{s.title}</span>
                      <div className="meta">
                        <span className="wa-tag" style={{ color: SEVC[s.severity], background: `color-mix(in srgb, ${SEVC[s.severity]} 15%, transparent)` }}>{SEVW[s.severity]}</span>
                        <span className="wa-src">{s.source}</span>
                        <StatusBadge s={s} />
                      </div>
                      {store.isResolved(s)
                        ? <div className="wa-rec done"><Icon name="check" size={11} color="var(--green)" />{(s.journal[s.journal.length - 1] || {}).comment || "решено"}</div>
                        : <div className="wa-rec"><Icon name="zap" size={11} color="var(--cyan)" />Рекомендация: <b>{s.action}</b></div>}
                    </div>
                    <div className="right">
                      <div className="risk"><b style={{ color: SEVC[s.severity] }}>{s.metric}{s.unit}</b><small>{s.delta}</small></div>
                      <Icon name="chevron-right" size={18} />
                    </div>
                  </div>
                ))}
                {feed.length === 0 ? <div className="wa-empty">{st.activeFocus === "deviations" ? "Отклонений нет — всё под контролем 🟢" : "Нет сигналов в этом фокусе"}</div> : null}
              </div>
            </>
          ) : view === "journal" ? (
            <JournalView st={st} store={store} onOpen={(id) => { setView("feed"); setOpenId(id); }} />
          ) : view === "metrics" ? (
            <MetricsView st={st} onDrill={(sid) => { setView("feed"); setOpenId(sid); store.markRead(sid); }} />
          ) : (
            <ChatPanel store={store} st={st} />
          )}
        </div>
      </div>

      <div className={`wa-scrim ${open ? "open" : ""}`} onClick={() => setOpenId(null)} />
      <div className={`wa-drawer ${open ? "open" : ""}`}>
        {open ? <Drawer s={open} store={store} onClose={() => setOpenId(null)} goChat={() => { setOpenId(null); setView("chat"); }} /> : null}
      </div>
    </div>
  );
}

// ── Модалка комментария (отклонить / эскалировать / закрыть) ──
function CommentModal({ cfg, onSubmit, onCancel }) {
  const [text, setText] = useState("");
  const ref = useRef(null);
  useEffect(() => { ref.current && ref.current.focus(); }, []);
  const canSubmit = !cfg.required || text.trim().length >= 3;
  return (
    <div className="wa-modal-scrim" onClick={onCancel}>
      <div className="wa-modal" onClick={(e) => e.stopPropagation()}>
        <div className="wa-modal-h"><span style={{ color: cfg.color }}><Icon name={cfg.icon} size={18} /></span><b>{cfg.title}</b></div>
        <p className="wa-modal-sub">{cfg.sub}</p>
        <textarea ref={ref} className="wa-modal-ta" rows={3} placeholder={cfg.placeholder} value={text} onChange={(e) => setText(e.target.value)} />
        {cfg.quick ? <div className="wa-modal-quick">{cfg.quick.map((q) => <button key={q} onClick={() => setText(q)}>{q}</button>)}</div> : null}
        <div className="wa-modal-acts">
          <button className="wa-btn" onClick={onCancel}>Отмена</button>
          <button className="wa-btn primary" style={{ background: cfg.color, opacity: canSubmit ? 1 : 0.5 }} disabled={!canSubmit} onClick={() => onSubmit(text.trim())}>
            <Icon name={cfg.icon} size={15} />{cfg.cta}
          </button>
        </div>
      </div>
    </div>
  );
}

function Drawer({ s, store, onClose, goChat }) {
  const sev = SEVC[s.severity];
  const [modal, setModal] = useState(null);
  const resolved = store.isResolved(s);

  const MODALS = {
    reject: { title: "Отклонить сигнал", sub: "Укажите причину — почему сигнал не требует действий. Это сохранится в журнале.", placeholder: "Например: ложное срабатывание, уже учтено в плане…", cta: "Отклонить", icon: "arrow", color: "var(--text-3)", required: true, quick: ["Ложное срабатывание", "Уже учтено в плане", "Не наш приоритет сейчас"], run: (t) => store.rejectSignal(s.id, t) },
    escalate: { title: "Эскалировать", sub: "Кому и почему передаёте выше. Сигнал останется в работе с пометкой «эскалация».", placeholder: "Например: вынести на правление, нужно решение собственника…", cta: "Эскалировать", icon: "target", color: "var(--red)", required: false, quick: ["Вынести на правление", "Требует решения собственника", "Нужен бюджет"], run: (t) => store.escalateSignal(s.id, t) },
    close: { title: "Закрыть с комментарием", sub: "Опишите, ЧТО сделано. Без этого закрыть нельзя — так копится журнал решений.", placeholder: "Например: цены пересчитаны по 12 позициям, маржа восстановлена…", cta: "Закрыть сигнал", icon: "check", color: "var(--green)", required: true, quick: [s.action + " — выполнено", "Поручено " + s.owner, "Решено, под контролем"], run: (t) => store.closeSignal(s.id, t) },
  };

  return (
    <>
      <div className="wa-dh">
        <span className="wa-src" style={{ fontSize: 11 }}>Сигнал · {s.source}</span>
        <button className="wa-x" onClick={onClose}>×</button>
      </div>
      <div className="wa-dtags">
        <span className="wa-tag" style={{ color: sev, background: `color-mix(in srgb, ${sev} 16%, transparent)`, fontSize: 10 }}>{SEVW[s.severity]}</span>
        <span className="wa-tag" style={{ color: "var(--cyan)", background: "color-mix(in srgb, var(--cyan) 16%, transparent)", fontSize: 10 }}>AI {s.confidence}%</span>
        <StatusBadge s={s} />
      </div>
      <h2 className="wa-dtitle">{s.title}</h2>
      <div className="wa-dchart">
        <div className="h">Динамика показателя <span>наведите</span></div>
        <SignalLineChart series={s.series} target={s.target} eventIndex={s.event} eventLabel="сигнал" labels={["","","сейчас"]} unit={s.unit.trim()==="%"?"%":s.unit} betterDown={s.unit.trim()!=="%"} height={150} />
      </div>
      <div className="wa-dblock"><span>Причина</span><b>{s.cause}</b></div>
      <div className="wa-dblock risk"><span>Риск</span><b>{s.risk}</b></div>
      <div className="wa-dmeta">
        <div><span>Ответственный</span><b>{s.owner}</b></div>
        <div><span>Рекомендация AI</span><b>{s.action}</b></div>
      </div>

      {/* журнал решений по сигналу */}
      {s.journal && s.journal.length ? (
        <div className="wa-djournal">
          <span className="wa-djournal-h">Журнал</span>
          {s.journal.map((j, i) => <SignalJournalRow j={j} key={i} />)}
        </div>
      ) : null}

      {/* действия по статусу */}
      <div className="wa-dactions">
        {resolved ? (
          <>
            <div className="wa-resolved-note" style={{ borderColor: s.status === "closed" ? "color-mix(in srgb, var(--green) 40%, transparent)" : "var(--line)" }}>
              <b style={{ color: s.status === "closed" ? "var(--green)" : "var(--text-3)" }}>{s.status === "closed" ? "✓ Закрыт" : "Отклонён"}</b>
              <span>{(s.journal[s.journal.length - 1] || {}).comment}</span>
            </div>
            <button className="wa-btn" onClick={() => store.reopen(s.id)}><Icon name="arrow" size={15} />Вернуть в работу</button>
          </>
        ) : s.status === "new" ? (
          <>
            <button className="wa-btn primary" onClick={() => store.takeIntoWork(s.id)}><Icon name="zap" size={16} />Взять в работу</button>
            <div className="wa-dactions-row">
              <button className="wa-btn" onClick={() => setModal("reject")}><Icon name="arrow" size={15} />Отклонить</button>
              <button className="wa-btn" onClick={() => setModal("escalate")}><Icon name="target" size={15} />Эскалация</button>
            </div>
            <button className="wa-btn ghost" onClick={goChat}><Icon name="brain" size={15} />Спросить AI</button>
          </>
        ) : (
          <>
            <button className="wa-btn primary" style={{ background: "var(--green)" }} onClick={() => setModal("close")}><Icon name="check" size={16} />Закрыть с комментарием</button>
            <div className="wa-dactions-row">
              <button className="wa-btn" onClick={() => setModal("escalate")}><Icon name="target" size={15} />Эскалация</button>
              <button className="wa-btn" onClick={goChat}><Icon name="brain" size={15} />Спросить AI</button>
            </div>
          </>
        )}
      </div>

      {modal ? <CommentModal cfg={MODALS[modal]} onCancel={() => setModal(null)} onSubmit={(t) => { MODALS[modal].run(t); setModal(null); }} /> : null}
    </>
  );
}

const ACT_LABEL = { taken: ["Взят в работу", "var(--cyan)", "zap"], rejected: ["Отклонён", "var(--text-3)", "arrow"], escalated: ["Эскалация", "var(--red)", "target"], closed: ["Закрыт", "var(--green)", "check"], reopened: ["Возвращён в работу", "var(--cyan)", "arrow"] };
function SignalJournalRow({ j }) {
  const m = ACT_LABEL[j.action] || [j.action, "var(--text-3)", "signal"];
  return (
    <div className="wa-jrow">
      <span className="wa-jic" style={{ color: m[1] }}><Icon name={m[2]} size={13} color={m[1]} /></span>
      <div><b>{m[0]}</b>{j.comment ? <span className="cm">«{j.comment}»</span> : null}<small>{j.by}</small></div>
    </div>
  );
}

function JournalView({ st, store, onOpen }) {
  const resolved = st.signals.filter((s) => store.isResolved(s)).sort((a, b) => {
    const la = a.journal[a.journal.length - 1] || {}, lb = b.journal[b.journal.length - 1] || {};
    return (lb.ts || 0) - (la.ts || 0);
  });
  const inWork = st.signals.filter((s) => s.status === "in_work");
  return (
    <div className="wa-journal">
      <p className="wa-journal-lead">Каждое решение записано: что сделано, кто отвечал. Это институциональная память компании — совещание идёт по фактам, а не по памяти.</p>
      {inWork.length ? (
        <>
          <div className="wa-journal-sec"><span className="pulse-dot" style={{ background: "var(--cyan)" }} />В работе · {inWork.length}</div>
          {inWork.map((s) => (
            <div className="wa-jcard" key={s.id} onClick={() => onOpen(s.id)}>
              <span className="wa-bar" style={{ background: SEVC[s.severity] }} />
              <div className="b"><b>{s.title}</b><small>{s.owner}{s.escalated ? " · эскалация" : ""}</small></div>
              <StatusBadge s={s} />
            </div>
          ))}
        </>
      ) : null}
      <div className="wa-journal-sec">Решённые · {resolved.length}</div>
      {resolved.length === 0 ? <div className="wa-empty">Пока ничего не закрыто. Возьмите сигнал в работу и закройте с комментарием.</div> : null}
      {resolved.map((s) => {
        const last = s.journal[s.journal.length - 1] || {};
        return (
          <div className="wa-jcard done" key={s.id} onClick={() => onOpen(s.id)}>
            <span className="wa-bar" style={{ background: s.status === "closed" ? "var(--green)" : "var(--text-3)" }} />
            <div className="b"><b>{s.title}</b><small className="cmt">{s.status === "closed" ? "✓ " : "✕ "}«{last.comment}» — {last.by}</small></div>
            <StatusBadge s={s} />
          </div>
        );
      })}
    </div>
  );
}

function ChatPanel({ store, st }) {
  const ref = useRef(null);
  const top = [...st.signals].filter((s) => store.isOpen(s)).sort((a,b)=>({red:0,amber:1,green:2}[a.severity]-{red:0,amber:1,green:2}[b.severity]))[0] || st.signals[0];
  const [ctx, setCtx] = useState(top ? top.id : null);
  const sig = st.signals.find((s) => s.id === ctx) || top;
  const [msgs, setMsgs] = useState([]);
  const [draft, setDraft] = useState(""); const [typing, setTyping] = useState(false);
  useEffect(() => { setMsgs(sig ? [{ from: "system", text: `Контекст — сигнал «${sig.title}». Спросите о причине, риске или действии.` }] : []); }, [ctx]);
  useEffect(() => { if (ref.current) ref.current.scrollTo({ top: ref.current.scrollHeight, behavior: "smooth" }); }, [msgs, draft, typing]);
  function ask(q) {
    if (typing || !sig) return;
    const a = aiReply(sig, q);
    setMsgs((c) => [...c, { from: "user", text: q }]); setTyping(true);
    setTimeout(() => { let i = 0; const t = setInterval(() => { i += 2; setDraft(a.slice(0, i)); if (i >= a.length) { clearInterval(t); setMsgs((c) => [...c, { from: "system", text: a }]); setDraft(""); setTyping(false); } }, 16); }, 320);
  }
  if (!sig) return <div className="wa-empty">Нет активных сигналов</div>;
  return (
    <div className="wa-chat" style={{ maxWidth: 720, margin: "0 auto" }}>
      <div className="wa-chat-ctx">Контекст: <b>{sig.title}</b> · риск {sig.risk}</div>
      <div className="wa-chat-msgs" ref={ref}>
        {msgs.map((m, i) => <div key={i} className={`wa-msg ${m.from}`}>{m.text}</div>)}
        {typing ? <div className="wa-msg system">{draft || <span className="typing-dots"><i/><i/><i/></span>}</div> : null}
      </div>
      <div className="wa-prompts">
        {aiPrompts().map((p) => <button key={p} onClick={() => ask(p)} disabled={typing}>{p}</button>)}
      </div>
    </div>
  );
}

function MetricsView({ st, onDrill }) {
  const groups = ["Финансы", "Продажи", "Склад", "Клиенты"];
  return (
    <div className="wa-metrics">
      {groups.map((g) => (
        <div className="wa-mgroup" key={g}>
          <div className="wa-mgroup-h">{g}</div>
          <div className="wa-mgrid">
            {st.metrics.filter((m) => m.group === g).map((m) => {
              const sev = m.dir === "down" ? "red" : m.dir === "warn" ? "amber" : "green";
              const drill = !!m.signalId;
              return (
                <div className={`wa-mcard ${drill ? "drill" : ""}`} key={m.id} onClick={drill ? () => onDrill(m.signalId) : undefined}>
                  <div className="wa-mc-h"><span>{m.name}</span>{drill ? <span className="wa-mc-link"><Icon name="signal" size={12} />сигнал</span> : null}</div>
                  <div className="wa-mc-val">{m.value}<small>{m.unit}</small></div>
                  <div className={`wa-mc-d ${m.dir}`}>{m.delta}</div>
                  <div className="wa-mc-spark"><MicroSpark data={m.spark} severity={sev} width={150} height={30} /></div>
                </div>
              );
            })}
          </div>
        </div>
      ))}
    </div>
  );
}

window.WebApp = WebApp;
