// components.jsx — спільні компоненти

const { useState, useEffect, useMemo, useCallback } = React;

// ============ ПРИВІТАННЯ (кличний відмінок + час доби) ============
// Привітання на дашборді мусить братися із залогіненого користувача,
// а НЕ бути захардкодженим рядком. Бек так само має формувати його
// з імені автентифікованого користувача (див. backend-нотатку).
const VOCATIVE_MAP = {
  "Олена": "Олено", "Марія": "Маріє", "Андрій": "Андрію", "Тарас": "Тарасе",
  "Вікторія": "Вікторіє", "Дмитро": "Дмитре", "Сергій": "Сергію", "Ігор": "Ігорю",
  "Наталія": "Наталіє", "Олександр": "Олександре", "Михайло": "Михайле",
  "Оксана": "Оксано", "Тетяна": "Тетяно", "Юлія": "Юліє", "Павло": "Павле",
  "Петро": "Петре", "Іван": "Іване", "Богдан": "Богдане", "Роман": "Романе",
  "Володимир": "Володимире", "Анна": "Анно", "Ірина": "Ірино", "Катерина": "Катерино",
};
function firstNameVocative(fullName) {
  const first = String(fullName || "").trim().split(/\s+/)[0] || "";
  if (!first) return "";
  if (VOCATIVE_MAP[first]) return VOCATIVE_MAP[first];
  if (/ій$/.test(first)) return first.replace(/ій$/, "ію");   // Андрій → Андрію
  if (/ія$/.test(first)) return first.replace(/я$/, "є");      // Марія → Маріє
  if (/я$/.test(first)) return first.replace(/я$/, "е");
  if (/а$/.test(first)) return first.replace(/а$/, "о");       // Олена → Олено
  if (/о$/.test(first)) return first.replace(/о$/, "е");       // Дмитро → Дмитре
  if (/[бвгґджзйклмнпрстфхцчшщ]$/i.test(first)) return first + "е"; // Тарас → Тарасе
  return first;
}
function timeGreeting(hour) {
  const h = (hour == null) ? new Date().getHours() : hour;
  if (h >= 5 && h < 12) return "Доброго ранку";
  if (h >= 12 && h < 18) return "Доброго дня";
  return "Доброго вечора";
}
// user — об'єкт залогіненого користувача ({ name }); hour — необов'язково
function dashGreeting(user, hour) {
  const name = (user && user.name) || "Олена Кравченко";
  const voc = firstNameVocative(name);
  return timeGreeting(hour) + (voc ? ", " + voc : "");
}
window.firstNameVocative = firstNameVocative;
window.dashGreeting = dashGreeting;

// ============ ICONS (мінімум — лиш утиліти) ============
const Icon = {
  Check: () => <svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 6.5L4.5 9L10 3" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  Search: () => <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><circle cx="7" cy="7" r="5" stroke="currentColor" strokeWidth="1.5"/><path d="M11 11L14 14" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>,
  Plus: () => <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M6 1V11M1 6H11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>,
  X: () => <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 3L11 11M11 3L3 11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>,
  Arrow: () => <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M4 2L8 6L4 10" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  Sun: () => <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="3" stroke="currentColor" strokeWidth="1.5"/><path d="M8 1V2.5M8 13.5V15M1 8H2.5M13.5 8H15M3 3L4 4M12 12L13 13M3 13L4 12M12 4L13 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>,
  Moon: () => <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M13 9.5A6 6 0 016.5 3 6 6 0 1013 9.5z" stroke="currentColor" strokeWidth="1.5" strokeLinejoin="round"/></svg>,
};

// ============ NAV TREE ============
const NAV_TREE = [
  { id: "dashboard-section", label: "Дашборд", children: [
    { id: "dashboard", label: "Огляд директора" },
  ]},
  { id: "work", label: "Задачі", children: [
    { id: "today",   label: "Сьогодні" },
    { id: "week",    label: "Тиждень" },
    { id: "kanban",  label: "Канбан" },
    { id: "tree",    label: "Дерево" },
    { id: "objects", label: "Об'єкти" },
    { id: "projects", label: "Проєктна діяльність" },
    { id: "admin",   label: "Адміністративні" },
  ]},
  { id: "sales", label: "Продажі", children: [
    { id: "leads",     label: "Ліди" },
    { id: "clients",   label: "Замовники" },
    { id: "contracts", label: "Договори" },
    { id: "suppliers", label: "Підрядники" },
    { id: "materials", label: "База матеріалів" },
  ]},
  { id: "accounting", label: "Бухгалтерія", children: [
    // — Фінанси —
    { id: "receivables",    label: "Рахунки і дебіторка" },
    { id: "expenses",       label: "Витрати" },
    { id: "budgets",        label: "Бюджети об'єктів" },
    { id: "cashflow",       label: "Cash flow" },
    { id: "cash",           label: "Каса" },
    { id: "pnl",            label: "P&L" },
    { id: "vat",            label: "ПДВ" },
    { id: "fop_tax",        label: "Єдиний податок (ФОП)" },
    { id: "subpayments",    label: "Виплати підрядникам" },
    { id: "advances",       label: "Авансові звіти" },
    { id: "estimates",      label: "Кошториси" },
    // — Зарплата —
    { id: "payroll",        label: "Розрахунок ЗП" },
    { id: "registry",       label: "Реєстр виплат" },
    { id: "sick_pay",       label: "Лікарняні" },
    { id: "bonus_pay",      label: "13-та і річні" },
    { id: "history",        label: "Історія ЗП" },
    { id: "analytics",      label: "Аналітика ЗП" },
    // — Склад —
    { id: "assets",         label: "Майно" },
    { id: "inventory",      label: "Інвентаризація" },
    // — Звіти —
    { id: "internal_reports",    label: "Внутрішні звіти" },
    { id: "supervision_journal", label: "Журнал авт. нагляду" },
    { id: "completion_acts",     label: "Акти робіт" },
    { id: "report_templates",    label: "Шаблони звітів" },
  ]},
  { id: "hr", label: "Команда", children: [
    { id: "profiles",  label: "Профілі" },
    { id: "qualifications", label: "Кваліфікація" },
    { id: "kpi",       label: "KPI та 1:1" },
    { id: "time",      label: "Табель" },
    { id: "vacation",  label: "Відпустки" },
    { id: "documents", label: "Документи" },
    { id: "orders",    label: "Накази" },
    { id: "onboarding",label: "Онбординг" },
    { id: "training",  label: "Навчання" },
  ]},
  { id: "permits", label: "Дозвільні", children: [
    { id: "tu",       label: "Технічні умови" },
    { id: "dsns",     label: "ДСНС / Узгодж." },
    { id: "kep",      label: "КЕП-сертифікати" },
  ]},
  { id: "directory", label: "Довідники", children: [
    { id: "contacts",  label: "Контакти" },
    { id: "ngo_directory", label: "Партнери ГО" },
    { id: "templates", label: "Шаблони" },
  ]},
  { id: "settings", label: "Налаштування", children: [
    { id: "roles",         label: "Ролі та права" },
    { id: "company",       label: "Компанія" },
    { id: "legal_changes", label: "Юридичні зміни" },
    { id: "audit",         label: "Журнал аудиту" },
    { id: "notifications", label: "Сповіщення" },
    // — Інтеграції (перенесено сюди) —
    { id: "drive",        label: "Google Drive" },
    { id: "calendar",     label: "Calendar" },
    { id: "diia",         label: "Дія.Підпис" },
    { id: "bank",         label: "Банк (monobank)" },
    { id: "edessb",       label: "ЄДЕССБ" },
    { id: "telegram",     label: "Telegram" },
    { id: "vchasno",      label: "Vchasno" },
    { id: "prozorro",     label: "Prozorro" },
    { id: "tax",          label: "ДПС" },
    { id: "maps",         label: "Google Maps" },
    { id: "ai",           label: "AI-асистент" },
  ]},
];

window.NAV_TREE = NAV_TREE;
window.findNavSection = (pageId) =>
  NAV_TREE.find(s => s.children.some(c => c.id === pageId));

// ============ APP HEADER ============
function AppHeader({ page, setPage, theme, setTheme, role, setRole, counts, user, onLogout, onChangePassword, onNewTask }) {
  const section = window.findNavSection(page) || NAV_TREE[0];
  const child = section.children.find(c => c.id === page);

  // Click on top-level section → goes to first child
  const goToSection = (sec) => {
    if (sec.id === section.id) return;
    setPage(sec.children[0].id);
  };

  return (
    <header className="appbar">
      <div className="appbar-row appbar-row-primary">
        <div className="appbar-brand">
          <img src="logo-horizontal-black.svg" alt="УКРБУДПРОЄКТ" className="appbar-wordmark appbar-wordmark-black" />
          <img src="logo-horizontal-white.svg" alt="УКРБУДПРОЄКТ" className="appbar-wordmark appbar-wordmark-white" />
          <span className="appbar-erp-badge">ERP</span>
        </div>

        <nav className="appbar-nav">
          {NAV_TREE.map(s => (
            <button
              key={s.id}
              className={`appbar-nav-item ${section.id === s.id ? "is-active" : ""}`}
              onClick={() => goToSection(s)}
            >
              {s.label}
            </button>
          ))}
        </nav>

        <div className="appbar-tools">
          <div className="search appbar-search">
            <Icon.Search />
            <input placeholder="Знайти задачу, об'єкт, людину…" />
            <span className="search-kbd">⌘K</span>
          </div>

          <button className="btn btn-primary" onClick={onNewTask}>
            <Icon.Plus /> <span className="hide-sm">Нова задача</span>
          </button>

          <button
            className="theme-btn"
            onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
            aria-label="Перемкнути тему"
          >
            {theme === "dark" ? <Icon.Sun /> : <Icon.Moon />}
          </button>

          {(() => {
            const ROLE_UA = { director: "Директор", deputy: "Заступник директора", accountant: "Бухгалтер", gip: "ГІП", engineer: "Інженер", contractor: "Субпідряд", employee: "Співробітник" };
            const name = (user && user.name) || "Олена Кравченко";
            const initials = name.split(/\s+/).map(w => w[0]).slice(0, 2).join("").toUpperCase();
            const roleUa = ROLE_UA[role] || "Співробітник";
            return (
              <div className="appbar-user-wrap">
                <button className="appbar-user" title={roleUa}>
                  <span className="task-assignee" style={{width: 30, height: 30, fontSize: 11}}>{initials}</span>
                  <div className="appbar-user-meta">
                    <div className="appbar-user-name">{name}</div>
                    <div className="appbar-user-role">{roleUa}</div>
                  </div>
                </button>
                {onChangePassword && (
                  <button className="appbar-logout" onClick={onChangePassword} title="Змінити пароль">
                    <svg viewBox="0 0 16 16" width="15" height="15" fill="none"><path d="M10.5 6.5a2.5 2.5 0 1 0-2.45 2.5L6 11v1.5H4.5L3 14H1.5v-1.5L6.5 7.5a2.5 2.5 0 0 1 4-1" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/><circle cx="11" cy="5" r="1" fill="currentColor"/></svg>
                  </button>
                )}
                {onLogout && (
                  <button className="appbar-logout" onClick={onLogout} title="Вийти">
                    <svg viewBox="0 0 16 16" width="15" height="15" fill="none"><path d="M6 2H3a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3M10.5 11l3-3-3-3M13 8H6" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/></svg>
                  </button>
                )}
              </div>
            );
          })()}
        </div>
      </div>

      <div className="appbar-row appbar-row-secondary">
        <nav className="subnav">
          {section.children.map(c => {
            const count = counts[c.id];
            return (
              <button
                key={c.id}
                className={`subnav-item ${page === c.id ? "is-active" : ""}`}
                onClick={() => setPage(c.id)}
              >
                <span>{c.label}</span>
                {count != null && count > 0 && (
                  <span className="subnav-count">{count}</span>
                )}
              </button>
            );
          })}
        </nav>

        <div className="subnav-trail">
          <span>{section.label}</span>
          <span className="trail-sep">›</span>
          <span className="trail-current">{child?.label}</span>
        </div>
      </div>
    </header>
  );
}

window.AppHeader = AppHeader;

// ============ TASK ROW ============
function TaskRow({ task, onOpen, onToggle, showAssignee = true, dateLabel }) {
  const obj = window.getObject(task.obj);
  const team = window.getTeam(task.assignee);
  const isDone = task.status === "done";
  const isLive = task.status === "live";
  const isLate = task.status === "late";

  return (
    <div
      className={`task-row ${isDone ? "is-done" : ""} ${isLive ? "is-live" : ""} ${isLate ? "is-late" : ""}`}
      onClick={() => onOpen(task)}
    >
      <button
        className="task-check"
        onClick={(e) => { e.stopPropagation(); onToggle(task); }}
        aria-label={isDone ? "Зняти позначку" : "Виконано"}
      >
        <Icon.Check />
      </button>

      <div className="task-main">
        <div className="task-title">{task.title}</div>
        <div className="task-meta">
          {task.private && <><span className="task-private-tag"><svg width="10" height="10" viewBox="0 0 12 12" fill="none" aria-hidden="true"><path d="M3 5V3.6a3 3 0 0 1 6 0V5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round"/><rect x="2.4" y="5" width="7.2" height="5.2" rx="1.2" fill="currentColor"/></svg>Приватне</span>{(task.kind === "visit" || obj || task.section) && <span className="task-meta-dot"></span>}</>}
          {task.kind === "visit" && window.VisitTypeBadge && <><window.VisitTypeBadge typeId={task.visit?.typeId} small={true} /><span className="task-meta-dot"></span></>}
          {obj ? <>
            <span className="task-obj">{obj.code}</span>
            <span className="task-meta-dot"></span>
            <span>{obj.name}</span>
          </> : (task.section && <span>{task.section}</span>)}
          {task.time && <>
            <span className="task-meta-dot"></span>
            <span>{task.time}</span>
          </>}
        </div>
      </div>

      <div className="task-right">
        {isLate && <span className="task-status is-late">Прострочено</span>}
        {isLive && <span className="task-status is-live">У роботі</span>}
        {dateLabel
          ? <span className={`task-date ${isLate ? "is-late" : ""}`}>{dateLabel}</span>
          : (!isDone && task.est && <span className="task-time">{task.est}</span>)
        }
        {showAssignee && team && (
          <div className="task-assignee" title={team.name}>{team.initials}</div>
        )}
      </div>
    </div>
  );
}

// ============ ПІДЗАДАЧІ (повноцінні міні-задачі) ============
function SubtaskRow({ s, team, onToggle, onUpdate, onRemove }) {
  const [editing, setEditing] = useState(false);
  const [val, setVal] = useState(s.title);
  useEffect(() => setVal(s.title), [s.title]);
  const person = s.assignee ? window.getTeam(s.assignee) : null;
  const saveTitle = () => { const v = val.trim(); if (v) onUpdate({ title: v }); else setVal(s.title); setEditing(false); };
  return (
    <div className={`st-row ${s.status === "done" ? "is-done" : ""}`}>
      <button className="st-check" onClick={onToggle} title={s.status === "done" ? "Зняти позначку" : "Позначити виконаним"}>{s.status === "done" && <Icon.Check />}</button>
      <div className="st-main">
        {editing
          ? <input className="cp-input st-edit" autoFocus value={val} onChange={(e) => setVal(e.target.value)} onBlur={saveTitle} onKeyDown={(e) => { if (e.key === "Enter") saveTitle(); if (e.key === "Escape") { setVal(s.title); setEditing(false); } }} />
          : <span className="st-title" onClick={() => setEditing(true)} title="Редагувати">{s.title}</span>}
        <div className="st-meta">
          <span className={`st-status-pill st-${s.status}`}>{s.status === "done" ? "Виконано" : s.status === "live" ? "У роботі" : s.status === "late" ? "Прострочено" : "To do"}</span>
          <select className="st-sel" value={s.status} onChange={(e) => onUpdate({ status: e.target.value })}>
            <option value="todo">To do</option>
            <option value="live">У роботі</option>
            <option value="late">Прострочено</option>
            <option value="done">Виконано</option>
          </select>
          <select className="st-sel" value={s.assignee || ""} onChange={(e) => onUpdate({ assignee: e.target.value || null })}>
            <option value="">Виконавець…</option>
            {team.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
          </select>
          {person && <span className="team-avatar st-av" title={person.name}>{person.initials}</span>}
          <input className="st-due" placeholder="дедлайн" value={s.due || ""} onChange={(e) => onUpdate({ due: e.target.value || null })} />
        </div>
      </div>
      <button className="st-del" onClick={onRemove} title="Видалити підзадачу"><Icon.X /></button>
    </div>
  );
}

function SubtasksBlock({ task, subtasks, done, onTaskPatch }) {
  const [adding, setAdding] = useState("");
  const team = window.DATA.TEAM || [];
  const patchList = (fn) => onTaskPatch(task.id, (x) => ({ ...x, subtasks: fn(x.subtasks || []) }));
  const add = () => {
    const title = adding.trim(); if (!title) return;
    patchList(list => [...list, { id: "st-" + Math.random().toString(36).slice(2, 8), title, assignee: null, status: "todo", due: null }]);
    setAdding("");
  };
  const update = (id, patch) => patchList(list => list.map(s => s.id === id ? { ...s, ...patch } : s));
  const remove = (id) => patchList(list => list.filter(s => s.id !== id));
  const toggle = (id) => patchList(list => list.map(s => s.id === id ? { ...s, status: s.status === "done" ? "todo" : "done" } : s));

  return (
    <div className="drawer-section">
      <div className="drawer-section-h">Підзадачі{subtasks.length ? ` · ${done}/${subtasks.length}` : ""}</div>
      <div className="st-list">
        {subtasks.map(s => (
          <SubtaskRow key={s.id} s={s} team={team} onToggle={() => toggle(s.id)} onUpdate={(p) => update(s.id, p)} onRemove={() => remove(s.id)} />
        ))}
        {subtasks.length === 0 && <div className="st-empty">Підзадач ще немає — розбийте задачу на кроки з виконавцем і дедлайном.</div>}
      </div>
      <div className="st-add">
        <input className="cp-input st-add-input" placeholder="Нова підзадача…" value={adding} onChange={(e) => setAdding(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") add(); }} />
        <button className="btn btn-sm btn-primary" onClick={add} disabled={!adding.trim()} style={!adding.trim() ? { opacity: 0.5 } : {}}>Додати</button>
      </div>
    </div>
  );
}

// ============ ЧЕКЛІСТИ (групи простих пунктів) ============
function ChecklistItem({ it, onToggle, onRemove, onUpdate }) {
  const [editing, setEditing] = useState(false);
  const [val, setVal] = useState(it.text);
  useEffect(() => setVal(it.text), [it.text]);
  const save = () => { const v = val.trim(); if (v) onUpdate(v); else setVal(it.text); setEditing(false); };
  return (
    <div className={`subtask ${it.done ? "is-done" : ""}`}>
      <div className="subtask-check" onClick={onToggle} style={{ cursor: "pointer" }}>{it.done && <Icon.Check />}</div>
      {editing
        ? <input className="cp-input st-edit" autoFocus value={val} onChange={(e) => setVal(e.target.value)} onBlur={save} onKeyDown={(e) => { if (e.key === "Enter") save(); if (e.key === "Escape") { setVal(it.text); setEditing(false); } }} />
        : <span onClick={() => setEditing(true)} style={{ cursor: "text", flex: 1 }} title="Редагувати">{it.text}</span>}
      {it.hint && !editing && <span className="subtask-time">{it.hint}</span>}
      <button className="st-del" onClick={onRemove} title="Видалити пункт"><Icon.X /></button>
    </div>
  );
}

function ChecklistGroup({ g, onRename, onRemove, onAddItem, onToggle, onRemoveItem, onUpdateItem }) {
  const [adding, setAdding] = useState("");
  const [editTitle, setEditTitle] = useState(false);
  const [tval, setTval] = useState(g.title);
  useEffect(() => setTval(g.title), [g.title]);
  const done = g.items.filter(i => i.done).length;
  const pct = g.items.length ? Math.round(done / g.items.length * 100) : 0;
  const add = () => { const t = adding.trim(); if (!t) return; onAddItem(t); setAdding(""); };
  const saveTitle = () => { const v = tval.trim(); if (v) onRename(v); else setTval(g.title); setEditTitle(false); };
  return (
    <div className="cl-group">
      <div className="cl-group-head">
        {editTitle
          ? <input className="cp-input cl-title-edit" autoFocus value={tval} onChange={(e) => setTval(e.target.value)} onBlur={saveTitle} onKeyDown={(e) => { if (e.key === "Enter") saveTitle(); if (e.key === "Escape") { setTval(g.title); setEditTitle(false); } }} />
          : <span className="cl-group-title" onClick={() => setEditTitle(true)} title="Перейменувати">{g.title}</span>}
        <span className="cl-group-count">{done}/{g.items.length}</span>
        <button className="st-del" onClick={onRemove} title="Видалити групу"><Icon.X /></button>
      </div>
      {g.items.length > 0 && <div className="cl-progress"><div className="cl-progress-fill" style={{ width: pct + "%" }}></div></div>}
      <div className="cl-items">
        {g.items.map(it => (
          <ChecklistItem key={it.id} it={it} onToggle={() => onToggle(it.id)} onRemove={() => onRemoveItem(it.id)} onUpdate={(t) => onUpdateItem(it.id, t)} />
        ))}
      </div>
      <div className="st-add">
        <input className="cp-input st-add-input" placeholder="Новий пункт…" value={adding} onChange={(e) => setAdding(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") add(); }} />
        <button className="btn btn-sm" onClick={add} disabled={!adding.trim()} style={!adding.trim() ? { opacity: 0.5 } : {}}>+ Пункт</button>
      </div>
    </div>
  );
}

function ChecklistsBlock({ task, checklists, onTaskPatch }) {
  const [addingGroup, setAddingGroup] = useState(false);
  const [groupName, setGroupName] = useState("");
  const patch = (fn) => onTaskPatch(task.id, (x) => ({ ...x, checklists: fn(x.checklists || []) }));
  const addGroup = () => {
    const title = groupName.trim() || "Чек-ліст";
    patch(list => [...list, { id: "cl-" + Math.random().toString(36).slice(2, 8), title, items: [] }]);
    setGroupName(""); setAddingGroup(false);
  };
  const renameGroup = (gid, title) => patch(list => list.map(g => g.id === gid ? { ...g, title } : g));
  const removeGroup = (gid) => patch(list => list.filter(g => g.id !== gid));
  const addItem = (gid, text) => patch(list => list.map(g => g.id === gid ? { ...g, items: [...g.items, { id: "ci-" + Math.random().toString(36).slice(2, 8), text, done: false }] } : g));
  const toggleItem = (gid, iid) => patch(list => list.map(g => g.id === gid ? { ...g, items: g.items.map(it => it.id === iid ? { ...it, done: !it.done } : it) } : g));
  const removeItem = (gid, iid) => patch(list => list.map(g => g.id === gid ? { ...g, items: g.items.filter(it => it.id !== iid) } : g));
  const updateItem = (gid, iid, text) => patch(list => list.map(g => g.id === gid ? { ...g, items: g.items.map(it => it.id === iid ? { ...it, text } : it) } : g));

  return (
    <div className="drawer-section">
      <div className="drawer-section-h" style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <span>Чеклісти</span>
        {!addingGroup && <button className="btn btn-sm" onClick={() => setAddingGroup(true)}><Icon.Plus /> Група</button>}
      </div>
      {addingGroup && (
        <div className="st-add" style={{ marginBottom: 10 }}>
          <input className="cp-input st-add-input" autoFocus placeholder="Назва групи (напр. Перед здачею)" value={groupName} onChange={(e) => setGroupName(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") addGroup(); if (e.key === "Escape") setAddingGroup(false); }} />
          <button className="btn btn-sm btn-primary" onClick={addGroup}>Додати</button>
        </div>
      )}
      {checklists.length === 0 && !addingGroup && <div className="st-empty">Чеклістів немає. Додайте групу простих пунктів-галочок (можна кілька).</div>}
      {checklists.map(g => (
        <ChecklistGroup key={g.id} g={g}
          onRename={(t) => renameGroup(g.id, t)} onRemove={() => removeGroup(g.id)}
          onAddItem={(t) => addItem(g.id, t)} onToggle={(iid) => toggleItem(g.id, iid)}
          onRemoveItem={(iid) => removeItem(g.id, iid)} onUpdateItem={(iid, t) => updateItem(g.id, iid, t)} />
      ))}
    </div>
  );
}

// ============ DRAWER (розгорнута картка задачі) ============
const DRAWER_STATUSES = [
  { id: "todo", label: "To Do" },
  { id: "live", label: "У роботі" },
  { id: "late", label: "Прострочено" },
  { id: "done", label: "Виконано" },
];

function Drawer({ task, onClose, onStatusChange, onTaskPatch, onOpenProject }) {
  const [tab, setTab] = useState("details");
  const [draft, setDraft] = useState("");
  const [localComments, setLocalComments] = useState([]);
  useEffect(() => {
    const onKey = (e) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);
  useEffect(() => { setLocalComments([]); setDraft(""); setTab("details"); }, [task && task.id]);

  if (!task) return null;
  const isVisit = task.kind === "visit" && !!window.VisitPanel;
  const obj = window.getObject(task.obj);
  const team = window.getTeam(task.assignee);
  const ex = window.PM ? window.PM.taskExtras(task.id) : { timeLogged: 0, timeEst: null, deps: { blockedBy: [], blocks: [] }, files: [], comments: [], activity: [] };
  const subtasks = task.subtasks || [];
  const checklists = task.checklists || [];
  const assigneeIds = task.assignees && task.assignees.length ? task.assignees : (task.assignee ? [task.assignee] : []);
  const assigneePeople = assigneeIds.map(id => window.getTeam(id)).filter(Boolean);
  const subtaskDone = subtasks.filter(s => s.status === "done").length;
  const comments = [...(ex.comments || []), ...localComments];
  const timeEst = ex.timeEst || parseFloat(String(task.est || "0")) || null;
  const timePct = timeEst ? Math.min(100, Math.round((ex.timeLogged || 0) / timeEst * 100)) : 0;
  const findTask = (id) => (window.DATA.TASKS || []).find(t => t.id === id);

  const submitComment = () => {
    if (!draft.trim()) return;
    setLocalComments(c => [...c, { by: "ok", date: "щойно", text: draft.trim() }]);
    setDraft("");
  };

  const TABS = [
    { id: "details", label: "Деталі" },
    { id: "comments", label: `Коментарі${comments.length ? " · " + comments.length : ""}` },
    { id: "files", label: `Файли${ex.files && ex.files.length ? " · " + ex.files.length : ""}` },
    { id: "history", label: "Історія" },
  ];

  return (
    <>
      <div className="drawer-overlay" onClick={onClose}></div>
      <aside className="drawer drawer-wide">
        <div className="drawer-head">
          <button className="drawer-close" onClick={onClose}><Icon.X /></button>
          {obj && <button className="drawer-objlink td-mono" onClick={() => obj && onOpenProject && onOpenProject(obj.id)} title="Відкрити об'єкт">{obj?.code} ↗</button>}
          {isVisit && <span className="vt-badge"><window.Ico name="mapPin" size={12} /> Виїзд · {window.getVisitType(task.visit?.typeId).short}</span>}
          {task.status === "late" && <span className="task-status is-late">Прострочено</span>}
          {task.status === "live" && <span className="task-status is-live">У роботі</span>}
        </div>

        <div className="drawer-body">
          <h1 className="drawer-h1">{task.title}</h1>
          <div className="drawer-meta">
            <span>{obj?.name}</span>
            <span className="task-meta-dot"></span>
            <span>Розділ {task.section}</span>
            {task.time && <><span className="task-meta-dot"></span><span>{task.time}</span></>}
          </div>

          {/* Статус — сегментований перемикач (для виїзду статус веде фаза) */}
          {!isVisit && <div className="drawer-section">
            <div className="drawer-section-h">Статус</div>
            <div className="pw-seg">
              {DRAWER_STATUSES.map(s => (
                <button
                  key={s.id}
                  className={`pw-seg-btn ${task.status === s.id ? "is-on" : ""} seg-${s.id}`}
                  onClick={() => onStatusChange && onStatusChange(task.id, s.id)}
                >{s.label}</button>
              ))}
            </div>
          </div>}

          {/* Час + виконавець (для виїзду «хто їде» — у панелі виїзду) */}
          {!isVisit && <div className="drawer-section">
            <div className="drawer-cols">
              <div className="drawer-col">
                <div className="drawer-section-h">Час</div>
                <div className="drw-time">
                  <span className="drw-time-val">{ex.timeLogged || 0}<span className="drw-time-of"> / {timeEst || "—"} год</span></span>
                  <div className="drw-time-bar"><div className="drw-time-fill" style={{ width: timePct + "%" }}></div></div>
                </div>
                <button className="btn btn-sm" style={{ marginTop: 8 }}>+ Залогувати час</button>
              </div>
              <div className="drawer-col">
                <div className="drawer-section-h">{assigneePeople.length > 1 ? "Виконавці" : "Виконавець"}</div>
                {assigneePeople.length > 0 ? (
                  <div className="drw-assignee-list">
                    {assigneePeople.map((p, i) => (
                      <div key={i} className="drw-assignee">
                        <div className="team-avatar" style={{ width: 30, height: 30, fontSize: 11 }}>{p.initials}</div>
                        <div><div className="drw-assignee-name">{p.name}{i === 0 && assigneePeople.length > 1 ? " · відповідальний" : ""}</div><div className="drw-assignee-role">{p.role}</div></div>
                      </div>
                    ))}
                  </div>
                ) : (
                  <div className="drw-assignee-role">Не призначено</div>
                )}
                <button className="btn btn-sm" style={{ marginTop: 8 }}>Перепризначити</button>
              </div>
            </div>
          </div>}

          {/* Tabs */}
          <div className="tab-bar drawer-tabs">
            {TABS.map(tb => (
              <button key={tb.id} className={`tab ${tab === tb.id ? "is-active" : ""}`} onClick={() => setTab(tb.id)}>{tb.label}</button>
            ))}
          </div>

          {tab === "details" && isVisit && (
            <div>
              {task.note && (
                <div className="drawer-section">
                  <div className="drawer-section-h">Нотатка</div>
                  <div style={{ fontSize: 13.5, color: "var(--ink-2)", lineHeight: 1.5 }}>{task.note}</div>
                </div>
              )}
              <window.VisitPanel task={task} onTaskPatch={onTaskPatch} />
            </div>
          )}

          {tab === "details" && !isVisit && (
            <div>
              {task.note && (
                <div className="drawer-section">
                  <div className="drawer-section-h">Нотатка</div>
                  <div style={{ fontSize: 13.5, color: "var(--ink-2)", lineHeight: 1.5 }}>{task.note}</div>
                </div>
              )}
              <SubtasksBlock task={task} subtasks={subtasks} done={subtaskDone} onTaskPatch={onTaskPatch} />
              <ChecklistsBlock task={task} checklists={checklists} onTaskPatch={onTaskPatch} />
              {(ex.deps.blockedBy.length > 0 || ex.deps.blocks.length > 0) && (
                <div className="drawer-section">
                  <div className="drawer-section-h">Залежності</div>
                  {ex.deps.blockedBy.map(id => {
                    const dt = findTask(id);
                    return <div key={id} className="drw-dep is-blocked"><span className="drw-dep-tag">чекає на</span><span>{dt ? dt.title : "Зовнішня умова (геологія / ТУ)"}</span></div>;
                  })}
                  {ex.deps.blocks.map(id => {
                    const dt = findTask(id);
                    return <div key={id} className="drw-dep"><span className="drw-dep-tag is-blocks">блокує</span><span>{dt ? dt.title : id}</span></div>;
                  })}
                </div>
              )}
              <div className="drawer-section">
                <div className="drawer-section-h">Паспорт</div>
                <dl className="info-grid">
                  <div><dt>Об'єкт</dt><dd>{obj?.name}</dd></div>
                  <div><dt>Шифр</dt><dd className="td-mono" style={{ fontSize: 12 }}>{obj?.code}</dd></div>
                  <div><dt>Етап</dt><dd>{window.getStage(task.stage)?.name || "—"}</dd></div>
                  <div><dt>Клас</dt><dd>{obj?.grade}</dd></div>
                  <div><dt>Розділ</dt><dd>{task.section}</dd></div>
                  <div><dt>Оцінка</dt><dd>{task.est}</dd></div>
                </dl>
              </div>
            </div>
          )}

          {tab === "comments" && (
            <div className="drawer-section">
              {comments.length === 0 ? <div className="empty" style={{ padding: "12px 0" }}>Коментарів ще немає.</div> :
                <div className="drw-comments">
                  {comments.map((c, i) => {
                    const p = window.getTeam(c.by);
                    return (
                      <div key={i} className="drw-comment">
                        <div className="team-avatar" style={{ width: 28, height: 28, fontSize: 10 }}>{p?.initials || "?"}</div>
                        <div className="drw-comment-body">
                          <div className="drw-comment-top"><b>{p?.name || "Користувач"}</b><span className="drw-comment-date">{c.date}</span></div>
                          <div className="drw-comment-text">{c.text}</div>
                        </div>
                      </div>
                    );
                  })}
                </div>
              }
              <div className="drw-comment-input">
                <input className="cp-input" placeholder="Написати коментар…" value={draft} onChange={(e) => setDraft(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") submitComment(); }} />
                <button className="btn btn-primary" onClick={submitComment}>Надіслати</button>
              </div>
            </div>
          )}

          {tab === "files" && (
            <div className="drawer-section">
              {(!ex.files || ex.files.length === 0) ? <div className="empty" style={{ padding: "12px 0" }}>Файлів ще не додано.</div> :
                <div className="drw-files">
                  {ex.files.map((f, i) => {
                    const p = window.getTeam(f.by);
                    return (
                      <div key={i} className="drw-file">
                        <div className="drw-file-ic">{(f.name.split(".").pop() || "").toUpperCase().slice(0, 3)}</div>
                        <div className="drw-file-body">
                          <div className="drw-file-name">{f.name}</div>
                          <div className="drw-file-meta">{f.size} · {p?.initials} · {window.formatDate ? window.formatDate(f.date) : f.date}</div>
                        </div>
                        <button className="btn btn-ghost" style={{ fontSize: 12 }}>Drive ↗</button>
                      </div>
                    );
                  })}
                </div>
              }
              <button className="btn btn-sm" style={{ marginTop: 10 }}>+ Додати файл</button>
            </div>
          )}

          {tab === "history" && (
            <div className="drawer-section">
              {(!ex.activity || ex.activity.length === 0) ? <div className="empty" style={{ padding: "12px 0" }}>Історія порожня.</div> :
                <div className="drw-history">
                  {ex.activity.map((a, i) => {
                    const p = window.getTeam(a.by);
                    return (
                      <div key={i} className="drw-hist-row">
                        <span className="drw-hist-dot"></span>
                        <div className="drw-hist-body"><div className="drw-hist-text"><b>{p?.name?.split(" ")[0] || "Хтось"}</b> {a.text}</div><div className="drw-hist-date">{a.date}</div></div>
                      </div>
                    );
                  })}
                </div>
              }
            </div>
          )}
        </div>

        <div className="drawer-foot">
          {!isVisit && <button className="btn btn-primary" onClick={() => onStatusChange && onStatusChange(task.id, task.status === "live" ? "done" : "live")}>
            {task.status === "live" ? "Позначити виконаною" : "Взяти в роботу"}
          </button>}
          {obj && onOpenProject && <button className="btn" onClick={() => onOpenProject(obj.id)}>До об'єкта</button>}
        </div>
      </aside>
    </>
  );
}

window.AppHeader = AppHeader;
window.TaskRow = TaskRow;
window.Drawer = Drawer;
window.Icon = Icon;
