// MDM SORP — Платежи / Smart Table
// Default state shows ONLY data. Advanced features (column visibility,
// source badges, group, color, row height) live behind toolbar dropdowns.
// Click row → slide-over drawer. Double-click cell → inline edit.

(function () {
  const { useState, useEffect, useMemo, useRef, useCallback } = React;

  // ─────────────────────────────────────────────────────────────
  // Source meta — 7 sources, but indicator is OFF by default.
  // Toggle via toolbar.
  // ─────────────────────────────────────────────────────────────
  const ST_SOURCES = {
    amocrm:   { short: "Amo",    label: "AmoCRM",        color: "#FF8A0B" },
    asana:    { short: "Asana",  label: "Asana",         color: "#F06A6A" },
    sheets:   { short: "Sheets", label: "Google Sheets", color: "#0F9D58" },
    bank:     { short: "Bank",   label: "Банк",          color: "#2C5C8C" },
    manual:   { short: "Manual", label: "Вручную",       color: "#7A7468" },
    ai:       { short: "AI",     label: "AI-generated",  color: "#6E45E2" },
    verified: { short: "✓",      label: "Verified",      color: "#2F7D5B" },
  };

  // ─────────────────────────────────────────────────────────────
  // Reference data
  // ─────────────────────────────────────────────────────────────
  const VENDORS = [
    { id: "v_chem",  short: "Chemify",      country: "ae" },
    { id: "v_ineq",  short: "Ineq",         country: "ae" },
    { id: "v_axis",  short: "Axis",         country: "ae" },
    { id: "v_andr",  short: "Andritz CN",   country: "cn" },
    { id: "v_meta",  short: "Метафракс",    country: "ru" },
    { id: "v_tmk",   short: "ТМК-Волжский", country: "ru" },
    { id: "v_sib",   short: "СИБУР",        country: "ru" },
    { id: "v_keng",  short: "Keshang Eng.", country: "cn" },
  ];
  const PEOPLE = [
    { id: "u_aa", name: "Aleksey A.",  role: "PM" },
    { id: "u_az", name: "Azat D.",     role: "Buyer" },
    { id: "u_es", name: "Елена С.",    role: "PM" },
    { id: "u_vk", name: "Валентин К.", role: "Buyer" },
    { id: "u_ai", name: "ИИ-агент",    role: "AI"   },
  ];
  const STATUS = {
    "new":      { label: "Новая",      color: "#7A7468" },
    "matched":  { label: "Согласовано",color: "#2F7D5B" },
    "conflict": { label: "Конфликт",   color: "#A1242E" },
    "approved": { label: "Одобрено",   color: "#1A4173" },
    "synced":   { label: "Закрыто",    color: "#4A2BA8" },
  };

  const c = (v, src = "manual", extra = {}) => ({ v, src, ...extra });

  // Realistic data — 14 rows
  const INITIAL_ROWS = [
    { id: "p1",  sorp: c("SORP-3606", "asana"), vendor: c("v_meta", "amocrm"), status: c("matched", "ai", { conf: 0.88 }), amount: c(10000, "bank"), currency: c("AED"), due: c("2026-06-04", "amocrm"), assignee: c("u_aa"), vat: c(20), docs: c(["spec.pdf","kp_v3.xlsx"], "sheets"), sanctions: c(false), comments: 2, history: 4 },
    { id: "p2",  sorp: c("SORP-3560", "asana"), vendor: c("v_andr", "ai", { conf: 0.71, edited: true }), status: c("conflict", "manual", { error: "Asana=В работе, Amo=Lost" }), amount: c(48750, "manual", { edited: true }), currency: c("USD"), due: c("2026-06-12", "amocrm"), assignee: c("u_az"), vat: c(0), docs: c(["invoice.pdf"], "sheets"), sanctions: c(false), comments: 5, history: 9 },
    { id: "p3",  sorp: c("SORP-3534", "asana"), vendor: c("v_andr", "amocrm"), status: c("approved", "manual"), amount: c(2890, "bank"), currency: c("USD"), due: c("2026-05-30", "amocrm", { error: "Просрочено на 3 дня" }), assignee: c("u_az"), vat: c(20), docs: c([]), sanctions: c(false), comments: 0, history: 2 },
    { id: "p4",  sorp: c("SORP-3533", "asana"), vendor: c("v_chem"), status: c("synced", "ai", { conf: 0.95 }), amount: c(127500, "bank"), currency: c("AED"), due: c("2026-07-15", "amocrm"), assignee: c("u_es"), vat: c(5), docs: c(["contract_v2.pdf","spec.docx","photo_1.jpg"], "sheets"), sanctions: c(false), comments: 1, history: 6 },
    { id: "p5",  sorp: c("SORP-3366", "asana"), vendor: c("v_meta", "amocrm"), status: c("matched"), amount: c(null, "ai", { conf: 0.42, suggested: 3500 }), currency: c("EUR", "ai", { conf: 0.42 }), due: c("2026-06-20"), assignee: c("u_ai", "ai"), vat: c(20), docs: c(["zayavka.pdf"], "sheets"), sanctions: c(false), comments: 3, history: 1 },
    { id: "p6",  sorp: c("SORP-3201", "asana"), vendor: c("v_tmk", "amocrm"), status: c("new"), amount: c(8400000, "sheets"), currency: c("RUB", "sheets"), due: c("2026-06-28"), assignee: c("u_aa"), vat: c(20), docs: c(["оферта.docx"], "sheets"), sanctions: c(true, "verified", { error: "Возможный hit OFAC" }), comments: 0, history: 1 },
    { id: "p7",  sorp: c("SORP-3198", "asana"), vendor: c("v_sib", "amocrm"), status: c("matched", "ai", { conf: 0.93 }), amount: c(2150000, "bank"), currency: c("RUB", "bank"), due: c("2026-06-15"), assignee: c("u_es"), vat: c(20), docs: c(["спец.xlsx","договор.pdf"], "sheets"), sanctions: c(false), comments: 1, history: 5 },
    { id: "p8",  sorp: c("SORP-3174", "asana"), vendor: c("v_andr", "amocrm"), status: c("approved"), amount: c(75200, "bank"), currency: c("USD"), due: c("2026-07-02"), assignee: c("u_vk"), vat: c(0), docs: c(["invoice_andr_174.pdf","cert.pdf"], "sheets"), sanctions: c(false), comments: 0, history: 3 },
    { id: "p9",  sorp: c("SORP-3155", "asana"), vendor: c("v_keng"), status: c("matched"), amount: c(34800, "manual", { edited: true }), currency: c("USD"), due: c("2026-06-22"), assignee: c("u_az"), vat: c(0), docs: c([]), sanctions: c(false), comments: 0, history: 1 },
    { id: "p10", sorp: c("SORP-3142", "asana"), vendor: c("v_ineq"), status: c("synced"), amount: c(18900, "bank"), currency: c("AED"), due: c("2026-05-28", "amocrm"), assignee: c("u_es"), vat: c(5), docs: c(["act.pdf"], "sheets"), sanctions: c(false), comments: 2, history: 8 },
    { id: "p11", sorp: c("SORP-3098", "asana"), vendor: c("v_meta", "amocrm"), status: c("new"), amount: c(null, "ai", { conf: 0.35, suggested: 1200 }), currency: c("USD", "ai"), due: c("2026-07-08"), assignee: c("u_ai", "ai"), vat: c(20), docs: c([]), sanctions: c(false), comments: 0, history: 1 },
    { id: "p12", sorp: c("SORP-3076", "asana"), vendor: c("v_axis"), status: c("approved"), amount: c(265000, "bank"), currency: c("AED"), due: c("2026-06-30"), assignee: c("u_aa"), vat: c(5), docs: c(["spec.pdf","contract.pdf"], "sheets"), sanctions: c(false), comments: 1, history: 4 },
    { id: "p13", sorp: c("SORP-3045", "asana"), vendor: c("v_andr"), status: c("conflict", "manual", { error: "Bank ≠ Контракт на 250 USD" }), amount: c(48500, "bank"), currency: c("USD"), due: c("2026-06-18"), assignee: c("u_vk"), vat: c(0), docs: c(["statement.csv"], "bank"), sanctions: c(false), comments: 3, history: 7 },
    { id: "p14", sorp: c("SORP-2998", "asana"), vendor: c("v_tmk", "amocrm"), status: c("matched"), amount: c(5600000, "sheets"), currency: c("RUB", "sheets"), due: c("2026-07-12"), assignee: c("u_aa"), vat: c(20), docs: c(["оферта.pdf"], "sheets"), sanctions: c(false), comments: 0, history: 2 },
  ];

  const INITIAL_COLS = [
    { key: "sorp",      label: "№",          type: "text",     w: 110, frozen: true },
    { key: "vendor",    label: "Контрагент", type: "linked",   w: 200 },
    { key: "status",    label: "Статус",     type: "select",   w: 150 },
    { key: "amount",    label: "Сумма",      type: "currency", w: 160 },
    { key: "due",       label: "Срок",       type: "date",     w: 130 },
    { key: "assignee",  label: "Исполнитель",type: "person",   w: 170 },
    // Hidden by default — surface in drawer
    { key: "vat",       label: "НДС %",      type: "number",   w: 80,  hidden: true },
    { key: "docs",      label: "Документы",  type: "attachment", w: 200, hidden: true },
    { key: "sanctions", label: "Скрин.",     type: "bool",     w: 80, hidden: true },
  ];

  const VIEWS = [
    { id: "v_all",      name: "Все",            filters: [] },
    { id: "v_overdue",  name: "Просроченные",   filters: [{ col: "due", op: "before", val: "today" }] },
    { id: "v_conflict", name: "Конфликты",      filters: [{ col: "status", op: "is", val: "conflict" }] },
    { id: "v_my",       name: "Мои (Елена)",    filters: [{ col: "assignee", op: "is", val: "u_es" }] },
    { id: "v_audit",    name: "Аудит > 50k",    filters: [{ col: "amount", op: "gt", val: 50000 }], locked: true },
  ];

  // ─────────────────────────────────────────────────────────────
  // Tiny components
  // ─────────────────────────────────────────────────────────────
  function SrcDot({ src, conf, edited }) {
    if (!src || src === "manual") return null;
    const m = ST_SOURCES[src];
    if (!m) return null;
    const title = m.label + (conf != null && conf < 1 ? ` · ${Math.round(conf * 100)}%` : "");
    return <span className="st2-src" style={{ background: m.color }} title={title}/>;
  }

  function StatusDot({ v }) {
    const m = STATUS[v];
    if (!m) return <span className="st2-muted">—</span>;
    return (
      <span className="st2-status">
        <span className="st2-status-dot" style={{ background: m.color }}/>
        <span className="st2-status-label">{m.label}</span>
      </span>
    );
  }

  function Linked({ id }) {
    const v = VENDORS.find(x => x.id === id);
    if (!v) return <span className="st2-muted">—</span>;
    return (
      <span className="st2-linked">
        <Flag code={v.country}/>
        <span className="st2-linked-name">{v.short}</span>
        <button className="st2-linked-open" title="Открыть карточку" tabIndex={-1}>
          <Icon name="arrow_up_right" size={11}/>
        </button>
      </span>
    );
  }

  function DateCell({ v }) {
    if (!v) return <span className="st2-muted">—</span>;
    const d = new Date(v);
    const today = new Date(); today.setHours(0,0,0,0);
    const days = Math.round((d - today) / 86400000);
    const overdue = days < 0;
    const soon = days >= 0 && days <= 3;
    return (
      <span className={"st2-date" + (overdue ? " overdue" : soon ? " soon" : "")}>
        <span>{d.toLocaleDateString("ru-RU", { day: "2-digit", month: "short" })}</span>
        {(overdue || soon) && (
          <span className="st2-date-rel">
            {overdue ? `${days} дн` : `+${days} дн`}
          </span>
        )}
      </span>
    );
  }

  function Person({ id }) {
    const p = PEOPLE.find(x => x.id === id);
    if (!p) return <span className="st2-muted">—</span>;
    return (
      <span className="st2-person">
        <Avatar name={p.name} size={22}/>
        <span>{p.name}</span>
      </span>
    );
  }

  function Money({ v, ccy }) {
    if (v == null) return <span className="st2-muted">—</span>;
    return <span className="st2-money">{fmtMoney(v, ccy)}</span>;
  }

  function AiSuggest({ value, ccy, onApply, onDismiss }) {
    return (
      <span className="st2-ai">
        <Icon name="sparkle" size={10}/>
        <span>≈{fmtMoney(value, ccy)}</span>
        <button className="st2-ai-yes" onClick={onApply} title="Применить">✓</button>
        <button className="st2-ai-no"  onClick={onDismiss} title="Отклонить">×</button>
      </span>
    );
  }

  // Generic cell renderer
  function Cell({ cell, col, row, showSrc }) {
    if (col.type === "select")     return <StatusDot v={cell.v}/>;
    if (col.type === "linked")     return <Linked id={cell.v}/>;
    if (col.type === "date")       return <DateCell v={cell.v}/>;
    if (col.type === "person")     return <Person id={cell.v}/>;
    if (col.type === "currency") {
      if (cell.v == null && cell.suggested != null) {
        return <AiSuggest value={cell.suggested} ccy={row.currency?.v}/>;
      }
      return <Money v={cell.v} ccy={row.currency?.v}/>;
    }
    if (col.type === "number")     return <span className="st2-money">{cell.v}</span>;
    if (col.type === "bool")       {
      return cell.v
        ? <span className="st2-sanc flag" title="Возможный hit OFAC"><Icon name="shield" size={13}/></span>
        : <span className="st2-sanc clean" title="Чисто"><Icon name="shield" size={13}/></span>;
    }
    if (col.type === "attachment") {
      const arr = cell.v || [];
      if (!arr.length) return <span className="st2-muted">—</span>;
      return (
        <span className="st2-files">
          {arr.slice(0, 2).map((f, i) => (
            <span key={i} className="st2-file" title={f}>
              <Icon name={/\.(jpg|jpeg|png)$/i.test(f) ? "image" : "file"} size={10}/>
              <span>{f.length > 16 ? f.slice(0, 14) + "…" : f}</span>
            </span>
          ))}
          {arr.length > 2 && <span className="st2-file-more">+{arr.length - 2}</span>}
        </span>
      );
    }
    return <span>{cell.v ?? "—"}</span>;
  }

  // ─────────────────────────────────────────────────────────────
  // Main screen
  // ─────────────────────────────────────────────────────────────
  function SmartTableScreen() {
    const [rows, setRows] = useState(INITIAL_ROWS);
    const [cols, setCols] = useState(INITIAL_COLS);
    const [viewId, setViewId] = useState("v_all");
    const [selected, setSelected] = useState(new Set());
    const [search, setSearch] = useState("");
    const [showSrc, setShowSrc] = useState(false);   // source dots toggle (OFF default)
    const [activeRowId, setActiveRowId] = useState(null);
    const [activePanel, setActivePanel] = useState("info");
    const [openMenu, setOpenMenu] = useState(null);   // 'columns' | 'sort' | 'group' | 'more' | 'view'
    const [editCell, setEditCell] = useState(null);
    const toast = useToast();

    const view = VIEWS.find(v => v.id === viewId);
    const visibleCols = cols.filter(c => !c.hidden);

    // Filter + search
    const filtered = useMemo(() => {
      let res = rows;
      if (search.trim()) {
        const q = search.toLowerCase();
        res = res.filter(r => {
          for (const k of Object.keys(r)) {
            const cell = r[k];
            if (cell && typeof cell === "object" && cell.v != null && String(cell.v).toLowerCase().includes(q)) return true;
          }
          return false;
        });
      }
      const today = new Date(); today.setHours(0,0,0,0);
      for (const f of (view?.filters || [])) {
        res = res.filter(r => {
          const cell = r[f.col];
          if (!cell) return false;
          if (f.op === "is")  return cell.v === f.val;
          if (f.op === "gt")  return Number(cell.v) > Number(f.val);
          if (f.op === "before") {
            if (f.val === "today") return new Date(cell.v) < today;
            return false;
          }
          return true;
        });
      }
      return res;
    }, [rows, search, view]);

    const toggleSelect = (id) => {
      const next = new Set(selected);
      if (next.has(id)) next.delete(id); else next.add(id);
      setSelected(next);
    };
    const toggleAll = () => {
      if (selected.size === filtered.length) setSelected(new Set());
      else setSelected(new Set(filtered.map(r => r.id)));
    };
    const toggleCol = (key) => setCols(prev => prev.map(c => c.key === key ? { ...c, hidden: !c.hidden } : c));

    const startEdit = (rowId, colKey) => setEditCell({ rowId, colKey });
    const commitEdit = (rowId, colKey, newVal) => {
      setRows(prev => prev.map(r => r.id !== rowId ? r : {
        ...r,
        [colKey]: { ...r[colKey], v: (typeof r[colKey].v === "number") ? Number(newVal) : newVal, src: "manual", edited: true }
      }));
      setEditCell(null);
    };

    const bulkApprove = () => {
      setRows(prev => prev.map(r => selected.has(r.id) ? { ...r, status: { v: "approved", src: "manual", edited: true } } : r));
      toast(`Одобрено: ${selected.size}`, { icon: "check", onUndo: () => setRows(INITIAL_ROWS) });
      setSelected(new Set());
    };

    const dirty = rows.reduce((s, r) => s + Object.values(r).filter(v => v && typeof v === "object" && v.edited).length, 0);
    const errors = rows.reduce((s, r) => s + Object.values(r).filter(v => v && typeof v === "object" && v.error).length, 0);

    const activeRow = activeRowId ? rows.find(r => r.id === activeRowId) : null;

    // Close menus on outside click
    useEffect(() => {
      if (!openMenu) return;
      const h = (e) => {
        if (!e.target.closest(".st2-menu") && !e.target.closest(".st2-tool")) setOpenMenu(null);
      };
      const t = setTimeout(() => document.addEventListener("click", h), 0);
      return () => { clearTimeout(t); document.removeEventListener("click", h); };
    }, [openMenu]);

    return (
      <div className="st2">
        {/* HEADER */}
        <header className="st2-header">
          <div>
            <h1 className="st2-title">Платежи</h1>
            <div className="st2-meta">
              <span><strong>{filtered.length}</strong> записей</span>
              {dirty > 0 && <span className="st2-meta-warn"><span className="st2-meta-dot"/>{dirty} несохранённых</span>}
              {errors > 0 && <span className="st2-meta-err"><span className="st2-meta-dot"/>{errors} конфликтов</span>}
            </div>
          </div>
          <div className="st2-header-right">
            {dirty > 0 && (
              <button className="st2-btn ghost" onClick={() => { setRows(INITIAL_ROWS); toast("Изменения отменены"); }}>
                Отменить
              </button>
            )}
            <button className="st2-btn primary" onClick={() => toast("Сохранено", { icon: "check" })}>
              <Icon name="check" size={14}/> Сохранить
            </button>
          </div>
        </header>

        {/* TOOLBAR — one line, minimal */}
        <div className="st2-toolbar">
          {/* View dropdown */}
          <div className="st2-tool-wrap">
            <button className="st2-tool" onClick={() => setOpenMenu(openMenu === "view" ? null : "view")}>
              <Icon name="eye" size={13}/>
              <span>{view.name}</span>
              {view.locked && <Icon name="shield" size={10}/>}
              <Icon name="chevron_down" size={10}/>
            </button>
            {openMenu === "view" && (
              <div className="st2-menu" style={{ minWidth: 220 }}>
                <div className="st2-menu-title">Представления</div>
                {VIEWS.map(v => (
                  <button key={v.id} className={"st2-menu-row" + (v.id === viewId ? " active" : "")}
                          onClick={() => { setViewId(v.id); setOpenMenu(null); }}>
                    <Icon name={v.locked ? "shield" : "list"} size={12}/>
                    <span>{v.name}</span>
                    {v.id === viewId && <Icon name="check" size={11}/>}
                  </button>
                ))}
                <div className="st2-menu-sep"/>
                <button className="st2-menu-row add">
                  <Icon name="plus" size={11}/>
                  <span>Новое представление</span>
                </button>
              </div>
            )}
          </div>

          {/* Filter pill (shows count if active) */}
          <button className={"st2-tool" + (view.filters.length ? " active" : "")}
                  onClick={() => toast("Конструктор фильтров — открывает popover")}>
            <Icon name="filter" size={13}/>
            <span>Фильтр</span>
            {view.filters.length > 0 && <span className="st2-tool-count">{view.filters.length}</span>}
          </button>

          {/* Sort */}
          <button className="st2-tool" onClick={() => toast("Сортировка — открывает popover")}>
            <Icon name="sort" size={13}/>
            <span>Сорт.</span>
          </button>

          {/* Group */}
          <button className="st2-tool" onClick={() => toast("Группировка — открывает popover")}>
            <Icon name="group" size={13}/>
            <span>Группа</span>
          </button>

          {/* Source toggle — the key user-control */}
          <button className={"st2-tool" + (showSrc ? " active" : "")}
                  onClick={() => setShowSrc(s => !s)}
                  title="Показать индикатор источника на ячейках">
            <Icon name="sparkle" size={13}/>
            <span>Источники</span>
          </button>

          {/* More menu — columns, height, color, AI-fill, export */}
          <div className="st2-tool-wrap">
            <button className="st2-tool" onClick={() => setOpenMenu(openMenu === "more" ? null : "more")}>
              <Icon name="more" size={13}/>
            </button>
            {openMenu === "more" && (
              <div className="st2-menu" style={{ minWidth: 200, right: 0, left: "auto" }}>
                <div className="st2-menu-title">Колонки</div>
                {cols.map(col => (
                  <label key={col.key} className="st2-menu-row toggle">
                    <input type="checkbox" checked={!col.hidden} onChange={() => toggleCol(col.key)}/>
                    <span>{col.label}</span>
                  </label>
                ))}
                <div className="st2-menu-sep"/>
                <button className="st2-menu-row" onClick={() => { toast("Запущен AI-fill", { icon: "sparkle" }); setOpenMenu(null); }}>
                  <Icon name="sparkle" size={11}/>
                  <span>AI-fill пустых ячеек</span>
                </button>
                <button className="st2-menu-row" onClick={() => { toast("Экспорт CSV"); setOpenMenu(null); }}>
                  <Icon name="download" size={11}/>
                  <span>Экспортировать CSV</span>
                </button>
                <button className="st2-menu-row" onClick={() => { toast("История на уровне таблицы"); setOpenMenu(null); }}>
                  <Icon name="history" size={11}/>
                  <span>История изменений</span>
                </button>
              </div>
            )}
          </div>

          <div className="st2-toolbar-grow"/>

          {/* Search */}
          <div className="st2-search">
            <Icon name="search" size={12}/>
            <input placeholder="Поиск…" value={search} onChange={(e) => setSearch(e.target.value)}/>
          </div>
        </div>

        {/* TABLE */}
        <div className="st2-grid">
          <table>
            <colgroup>
              <col style={{ width: 40 }}/>
              {visibleCols.map(c => <col key={c.key} style={{ width: c.w }}/>)}
              <col style={{ width: 40 }}/>
            </colgroup>
            <thead>
              <tr>
                <th>
                  <input type="checkbox"
                         checked={filtered.length > 0 && selected.size === filtered.length}
                         onChange={toggleAll}/>
                </th>
                {visibleCols.map(col => (
                  <th key={col.key} className={col.frozen ? "frozen" : ""}>
                    <span>{col.label}</span>
                  </th>
                ))}
                <th/>
              </tr>
            </thead>
            <tbody>
              {filtered.map(row => {
                const isActive = activeRowId === row.id;
                const isSelected = selected.has(row.id);
                const hasError = Object.values(row).some(c => c && typeof c === "object" && c.error);
                return (
                  <tr key={row.id}
                      className={
                        "st2-row" +
                        (isSelected ? " selected" : "") +
                        (isActive ? " active" : "") +
                        (hasError ? " has-error" : "")
                      }
                      onClick={(e) => {
                        if (e.target.closest("input,button,.st2-linked-open,.st2-ai-yes,.st2-ai-no")) return;
                        setActiveRowId(row.id);
                      }}>
                    <td className="st2-td-check" onClick={(e) => e.stopPropagation()}>
                      <input type="checkbox" checked={isSelected} onChange={() => toggleSelect(row.id)}/>
                    </td>
                    {visibleCols.map(col => {
                      const cell = row[col.key];
                      const isEditing = editCell && editCell.rowId === row.id && editCell.colKey === col.key;
                      const cellHasError = cell?.error;
                      const cellEdited = cell?.edited;
                      return (
                        <td key={col.key}
                            className={
                              "st2-td" +
                              (col.frozen ? " frozen" : "") +
                              (cellEdited ? " edited" : "") +
                              (cellHasError ? " error" : "")
                            }
                            onDoubleClick={(e) => {
                              e.stopPropagation();
                              if (col.type === "linked" || col.type === "person" || col.type === "select" || col.type === "bool") return;
                              startEdit(row.id, col.key);
                            }}
                            title={cellHasError || undefined}>
                          {isEditing ? (
                            <input className="st2-input" autoFocus
                                   defaultValue={cell?.v ?? ""}
                                   onBlur={(e) => commitEdit(row.id, col.key, e.target.value)}
                                   onKeyDown={(e) => {
                                     if (e.key === "Enter") e.currentTarget.blur();
                                     if (e.key === "Escape") setEditCell(null);
                                   }}/>
                          ) : (
                            <span className="st2-cell">
                              <Cell cell={cell} col={col} row={row} showSrc={showSrc}/>
                              {showSrc && <SrcDot src={cell?.src} conf={cell?.conf} edited={cell?.edited}/>}
                            </span>
                          )}
                        </td>
                      );
                    })}
                    <td className="st2-td-actions">
                      {row.comments > 0 && (
                        <span className="st2-row-act" title={`${row.comments} комментариев`}
                              onClick={(e) => { e.stopPropagation(); setActiveRowId(row.id); setActivePanel("comments"); }}>
                          <Icon name="more" size={11}/>
                          {row.comments}
                        </span>
                      )}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
          {/* Add row */}
          <button className="st2-add-row" onClick={() => toast("Добавить запись (форма)")}>
            <Icon name="plus" size={12}/>
            <span>Добавить запись</span>
          </button>
        </div>

        {/* Bulk floating bar (Linear-style) */}
        {selected.size > 0 && (
          <div className="st2-bulk">
            <span className="st2-bulk-count">
              <Icon name="check" size={12}/>
              {selected.size} выбрано
            </span>
            <button onClick={bulkApprove}>
              <Icon name="check" size={11}/>
              Одобрить
            </button>
            <button>
              <Icon name="pencil" size={11}/>
              Изменить
            </button>
            <button>
              <Icon name="download" size={11}/>
              Экспорт
            </button>
            <button className="danger">
              <Icon name="x" size={11}/>
              Удалить
            </button>
            <span className="st2-bulk-sep"/>
            <button className="st2-bulk-close" onClick={() => setSelected(new Set())}>
              <Icon name="x" size={11}/>
            </button>
          </div>
        )}

        {/* Row drawer */}
        <Drawer open={!!activeRow} onClose={() => setActiveRowId(null)} width={520}>
          {activeRow && (
            <div className="st2-drawer">
              <div className="st2-drawer-head">
                <div>
                  <div className="st2-drawer-tag">{activeRow.sorp.v}</div>
                  <h2 className="st2-drawer-title">{(VENDORS.find(v => v.id === activeRow.vendor.v) || {}).short || "—"}</h2>
                  <div className="st2-drawer-sub">
                    <StatusDot v={activeRow.status.v}/>
                    <span className="st2-muted">·</span>
                    <Money v={activeRow.amount.v} ccy={activeRow.currency.v}/>
                  </div>
                </div>
                <button className="icon-btn" onClick={() => setActiveRowId(null)}>
                  <Icon name="x" size={14}/>
                </button>
              </div>

              <div className="st2-drawer-tabs">
                <button className={activePanel === "info" ? "active" : ""} onClick={() => setActivePanel("info")}>
                  Поля
                </button>
                <button className={activePanel === "comments" ? "active" : ""} onClick={() => setActivePanel("comments")}>
                  Комменты {activeRow.comments > 0 && <span className="st2-tab-count">{activeRow.comments}</span>}
                </button>
                <button className={activePanel === "history" ? "active" : ""} onClick={() => setActivePanel("history")}>
                  История <span className="st2-tab-count">{activeRow.history}</span>
                </button>
              </div>

              {activePanel === "info" && (
                <div className="st2-drawer-fields">
                  <FieldRow label="№ SORP" value={activeRow.sorp.v} src={activeRow.sorp.src}/>
                  <FieldRow label="Контрагент" value={(VENDORS.find(v => v.id === activeRow.vendor.v) || {}).short} src={activeRow.vendor.src} conf={activeRow.vendor.conf}/>
                  <FieldRow label="Статус" value={STATUS[activeRow.status.v]?.label} src={activeRow.status.src}/>
                  <FieldRow label="Сумма" value={fmtMoney(activeRow.amount.v, activeRow.currency.v)} src={activeRow.amount.src} edited={activeRow.amount.edited}/>
                  <FieldRow label="Валюта" value={activeRow.currency.v} src={activeRow.currency.src}/>
                  <FieldRow label="Срок" value={activeRow.due.v} src={activeRow.due.src} error={activeRow.due.error}/>
                  <FieldRow label="Исполнитель" value={(PEOPLE.find(p => p.id === activeRow.assignee.v) || {}).name} src={activeRow.assignee.src}/>
                  <FieldRow label="НДС %" value={activeRow.vat.v + "%"} src={activeRow.vat.src}/>
                  <FieldRow label="Документы" value={(activeRow.docs.v || []).join(", ") || "—"} src={activeRow.docs.src}/>
                  <FieldRow label="Скрининг" value={activeRow.sanctions.v ? "🚩 Hit" : "✓ Чисто"} src={activeRow.sanctions.src} error={activeRow.sanctions.error}/>
                </div>
              )}

              {activePanel === "comments" && (
                <div className="st2-drawer-comments">
                  {activeRow.comments > 0 ? (
                    <>
                      <div className="st2-cm">
                        <Avatar name="Aleksey A." size={28}/>
                        <div>
                          <div className="st2-cm-head"><strong>Aleksey A.</strong> <span className="st2-muted">2 ч</span></div>
                          <div className="st2-cm-body">Сумма расходится с банком на 250.</div>
                        </div>
                      </div>
                      <div className="st2-cm">
                        <Avatar name="ИИ" size={28}/>
                        <div>
                          <div className="st2-cm-head"><strong>ИИ-агент</strong> <span className="st2-muted">3 ч</span></div>
                          <div className="st2-cm-body">Предлагаю статус <code>matched</code> (88%).</div>
                        </div>
                      </div>
                    </>
                  ) : (
                    <div className="st2-empty">Пока нет комментариев</div>
                  )}
                  <textarea className="st2-cm-add" placeholder="Комментарий, @упомяни…"/>
                </div>
              )}

              {activePanel === "history" && (
                <div className="st2-drawer-history">
                  <HistoryRow icon="pencil" what="amount" detail="48 500 → 48 750" who="Azat D." when="10 мин назад" src="manual"/>
                  <HistoryRow icon="sparkle" what="status" detail="predicted matched (88%)" who="ИИ-агент" when="22 мин" src="ai"/>
                  <HistoryRow icon="download" what="amount" detail="pulled $48 500" who="Bank statement" when="вчера" src="bank"/>
                  <HistoryRow icon="plus" what="row created" detail="from amo_lead_34953509" who="AmoCRM" when="3 дн" src="amocrm"/>
                </div>
              )}
            </div>
          )}
        </Drawer>
      </div>
    );
  }

  function FieldRow({ label, value, src, conf, edited, error }) {
    const m = src && src !== "manual" ? ST_SOURCES[src] : null;
    return (
      <div className={"st2-field" + (error ? " error" : "")}>
        <div className="st2-field-label">{label}</div>
        <div className="st2-field-val">
          <span>{value ?? "—"}</span>
          {m && (
            <span className="st2-field-src" style={{ background: m.color + "20", color: m.color }}>
              <span className="st2-src" style={{ background: m.color, width: 5, height: 5 }}/>
              {m.label}
              {conf != null && conf < 1 && <span style={{ opacity: 0.6, marginLeft: 4 }}>{Math.round(conf * 100)}%</span>}
            </span>
          )}
          {edited && <span className="st2-field-edited" title="Изменено локально">●</span>}
        </div>
        {error && <div className="st2-field-error">{error}</div>}
      </div>
    );
  }

  function HistoryRow({ icon, what, detail, who, when, src }) {
    const m = src && src !== "manual" ? ST_SOURCES[src] : null;
    return (
      <div className="st2-hist">
        <Icon name={icon} size={12}/>
        <div className="st2-hist-body">
          <div><strong>{what}</strong> <span className="st2-muted">{detail}</span></div>
          <div className="st2-muted st2-hist-meta">
            {who} · {when}
            {m && <span className="st2-src" style={{ background: m.color, width: 5, height: 5, marginLeft: 6, display: "inline-block" }}/>}
          </div>
        </div>
      </div>
    );
  }

  window.SmartTableScreen = SmartTableScreen;
})();
