// app.jsx — головний роутер + Tweaks

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "page": "dashboard",
  "density": "normal",
  "role": "director"
}/*EDITMODE-END*/;

// Об'єднана сторінка: Розрахунок ЗП + Аванси ЗП під вкладками
function PayrollWithAdvances({ role }) {
  const [tab, setTab] = React.useState("calc");
  return (
    <React.Fragment>
      <div className="page" style={{ paddingBottom: 0 }}>
        <div className="tab-bar">
          <button className={`tab ${tab === "calc" ? "is-active" : ""}`} onClick={() => setTab("calc")}>Розрахунок</button>
          <button className={`tab ${tab === "adv" ? "is-active" : ""}`} onClick={() => setTab("adv")}>Аванси</button>
        </div>
      </div>
      {tab === "calc" ? <window.PayrollPage role={role} /> : <window.AdvancePayPage role={role} />}
    </React.Fragment>
  );
}

function App() {
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const liveUser = (window.API && window.API.mode === "live") ? window.API.user : null;
  const [tasks, setTasks] = React.useState(window.DATA.TASKS);
  const [objects, setObjects] = React.useState(window.DATA.OBJECTS);
  const [drawerTask, setDrawerTask] = React.useState(null);
  const [openProjectId, setOpenProjectId] = React.useState(null);
  const [openGoProjId, setOpenGoProjId] = React.useState(null); // воркспейс проєкту ГО
  const [newTask, setNewTask] = React.useState(null); // null | preset-об'єкт (відкриває модалку «Нова задача»)
  const [newVisit, setNewVisit] = React.useState(null); // null | preset-об'єкт (відкриває модалку «Новий виїзд»)
  const [showPwd, setShowPwd] = React.useState(false); // модалка зміни пароля
  const [, setCareerTick] = React.useState(0); // форс-ререндер після кар'єрних змін у window.DATA.TEAM

  // Глобальний навігатор для крос-сторінкових переходів (табель ↔ ЗП тощо)
  React.useEffect(() => { window.__setPage = (p) => setTweak("page", p); }, [setTweak]);

  // LIVE-збереження: у режимі live шле зміну в API (оптимістично; алерт на збій).
  // У demo-режимі — нічого не робить (лишається локально).
  const liveSave = (resource, id, patch) => {
    if (!(window.API && window.API.mode === "live" && window.API.save)) return;
    Promise.resolve(window.API.save(resource, id, patch)).catch(err => {
      console.error("[ERP] save failed:", resource, id, err);
      alert("Не вдалося зберегти на сервері. Перевірте з'єднання і повторіть дію.");
    });
  };

  const onCreateTask = (task) => {
    const ready = window.normalizeTask ? window.normalizeTask(task) : task;
    setTasks(prev => [ready, ...prev]);
    setNewTask(null);
    setTweak("page", "kanban"); // переходимо на дошку — нова задача одразу видно карткою
    liveSave("tasks", null, ready);
  };
  const onCreateTasks = (newTasks) => {
    if (!newTasks || !newTasks.length) return;
    setTasks(prev => [...newTasks, ...prev]);
    newTasks.forEach(t => liveSave("tasks", null, t));
  };
  const onCreateVisit = (task) => {
    const ready = window.normalizeTask ? window.normalizeTask(task) : task;
    setTasks(prev => [ready, ...prev]);
    setNewVisit(null);
    setTweak("page", "kanban"); // новий виїзд одразу видно на дошці
    liveSave("tasks", null, ready);
  };

  // Глобальний стор: дозволяє window.createObjectFromTemplate синхронізувати React state
  React.useEffect(() => {
    window.__erpStore = {
      addObject: (newObj, newTasks) => {
        setObjects(prev => [newObj, ...prev]);
        setTasks(prev => [...prev, ...newTasks]);
      },
      updateObject: (id, patch, newTasks) => {
        window.DATA.OBJECTS = window.DATA.OBJECTS.map(o => o.id === id ? { ...o, ...patch } : o);
        setObjects(window.DATA.OBJECTS);
        if (newTasks && newTasks.length) {
          window.DATA.TASKS = [...window.DATA.TASKS, ...newTasks];
          setTasks(window.DATA.TASKS);
        }
      },
    };
    // Глобальний тогл статусу задачі за id (для віджетів, напр. нагадувань про ДН)
    window.__erpToggleTask = (id) => setTasks(prev => prev.map(x => x.id === id ? { ...x, status: x.status === "done" ? "todo" : "done" } : x));
    return () => { window.__erpStore = null; };
  }, []);

  // Тримаємо window.DATA.OBJECTS / TASKS у синхроні зі state (для функцій типу getObject)
  React.useEffect(() => { window.DATA.OBJECTS = objects; }, [objects]);
  React.useEffect(() => { window.DATA.TASKS = tasks; }, [tasks]);

  React.useEffect(() => { setDrawerTask(null); setOpenProjectId(null); setOpenGoProjId(null); }, [t.page]);

  React.useEffect(() => {
    document.documentElement.style.setProperty(
      "--dens",
      t.density === "compact" ? "0.85" : t.density === "spacious" ? "1.15" : "1"
    );
  }, [t.density]);

  React.useEffect(() => {
    const cls = t.theme === "dark" ? "theme-dark" : "theme-light";
    document.documentElement.classList.remove("theme-light", "theme-dark");
    document.documentElement.classList.add(cls);
  }, [t.theme]);

  const themeClass = t.theme === "dark" ? "theme-dark" : "theme-light";

  const onOpenTask = (task) => setDrawerTask(task);
  const onCloseTask = () => setDrawerTask(null);
  const onToggle = (task) => {
    const next = task.status === "done" ? "todo" : "done";
    setTasks(prev => prev.map(x => x.id === task.id ? { ...x, status: next } : x));
    liveSave("tasks", task.id, { status: next });
  };
  const onStatusChange = (taskId, status) => {
    setTasks(prev => prev.map(x => x.id === taskId ? { ...x, status } : x));
    setDrawerTask(d => d && d.id === taskId ? { ...d, status } : d);
    liveSave("tasks", taskId, { status });
  };
  // Універсальний апдейтер задачі: patch — об'єкт або функція (task) => task.
  // Через нього йдуть усі правки підзадач і чеклістів.
  const onTaskPatch = (taskId, patch) => {
    const apply = (x) => (typeof patch === "function" ? patch(x) : { ...x, ...patch });
    setTasks(prev => prev.map(x => x.id === taskId ? apply(x) : x));
    setDrawerTask(d => (d && d.id === taskId ? apply(d) : d));
    // Для функції-патча шлемо повний оновлений об'єкт (бек бере лише відомі поля);
    // для об'єкта-патча — самі змінені поля.
    const cur = (window.DATA.TASKS || tasks).find(x => x.id === taskId);
    if (cur) liveSave("tasks", taskId, typeof patch === "function" ? apply(cur) : patch);
  };

  // Оформлення кар'єрного переходу: міняє статус людини у window.DATA.TEAM
  // і породжує задачі-супровід за HR-шаблоном.
  const onPromote = (personId) => {
    const person = (window.DATA.TEAM || []).find(p => p.id === personId);
    if (!person) return;
    const st = window.careerState(person);
    if (!st || !st.promotion) return;
    const promo = st.promotion;
    const today = window.SYS_DATE;
    const fromPos = person.positionOfficial || person.role;

    // 1) Зміна посади / окладу
    if (promo.kind === "gap") {
      person.positionOfficial = promo.targetPosition;
      person.role = promo.targetRole || person.role;
    } else if (promo.kind === "category") {
      person.positionOfficial = promo.targetPosition;
    }
    if (promo.salaryDelta && (person.salaryModel === "fixed" || person.salaryModel === "fixed_bonus")) {
      person.baseSalary = (person.baseSalary || 0) + promo.salaryDelta;
    }
    person.careerLog = person.careerLog || [];
    person.careerLog.push({ date: today, from: fromPos, to: promo.targetPosition, delta: promo.salaryDelta, kind: promo.kind });

    // 2) Задачі-супровід із HR-шаблону
    const tpl = window.getHrProcessTemplate(promo.templateId);
    const dayNum = (window.TODAY && window.TODAY.day) || "29";
    const newTasks = ((tpl && tpl.taskTemplateIds) || []).map((id, i) => {
      const tt = window.getHrTaskTemplate(id);
      const cl = (tt && tt.checklist && tt.checklist.length)
        ? [{ id: `cl-hr-${person.id}-${id}`, title: "Чек-ліст", items: tt.checklist.map((text, j) => ({ id: `ci-hr-${person.id}-${id}-${j}`, text, done: false })) }]
        : [];
      return {
        id: `hr-${person.id}-${id}-${Math.random().toString(36).slice(2, 6)}`,
        title: `${tt ? tt.title : "Кадрова задача"} — ${person.name}`,
        obj: null, stage: "admin", section: "HR",
        assignee: tt && tt.assigneeRole === "accountant" ? "ok" : "ok",
        day: dayNum, est: tt ? `${tt.estDays} дн` : "1 дн",
        status: "todo", subtasks: [], checklists: cl,
        note: tpl ? `Кадровий процес: ${tpl.name}. ${promo.reason}` : promo.reason,
        hrFor: person.id,
      };
    });
    if (newTasks.length) setTasks(prev => [...newTasks, ...prev]);
    setCareerTick(x => x + 1);
  };

  // Роль і видимість
  const role = liveUser ? liveUser.role : (t.role || "director");
  const canSeeSalary = liveUser ? !!liveUser.canSeeSalary : (role === "director" || role === "accountant");
  // Приватні задачі (нагадування директора) бачить лише директор
  const visTasks = window.visibleTasks ? window.visibleTasks(tasks, role) : tasks;

  // Лічильники секцій
  const today = window.TODAY.day;
  const overdueInvoices = (window.DATA.INVOICES || []).filter(i => i.status === "overdue").length;
  const leads = window.DATA.LEADS || [];
  const counts = {
    dashboard: null,
    today: visTasks.filter(t => t.day === today && t.status !== "done").length,
    week: visTasks.filter(t => t.status !== "done").length,
    objects: window.DATA.OBJECTS.length,
    projects: window.DATA.PROJECTS ? window.DATA.PROJECTS.length : null,
    admin: visTasks.filter(t => !t.obj && t.status !== "done").length,
    leads: leads.filter(l => { const s = window.leadStage(l); return !s.terminal && !s.won; }).length || null,
    clients: window.DATA.CLIENTS ? window.DATA.CLIENTS.length : null,
    contracts: window.DATA.CONTRACTS ? window.DATA.CONTRACTS.filter(c => c.status === "active" || c.status === "supervision").length : null,
    receivables: overdueInvoices > 0 ? overdueInvoices : null,
    expenses: window.DATA.EXPENSES ? window.DATA.EXPENSES.length : null,
    budgets: null,
    estimates: null,
    profiles: window.DATA.TEAM.length,
    time: null,
    vacation: window.DATA.VACATIONS ? window.DATA.VACATIONS.filter(v => v.status === "pending").length : null,
    documents: window.DATA.DOCUMENTS ? window.DATA.DOCUMENTS.filter(d => d.status === "draft").length : null,
    payroll: null,
    registry: null,
    analytics: null,
    roles: null,
    company: null,
  };

  // Якщо співробітник зайшов у Зарплата — переадресуємо у профілі
  React.useEffect(() => {
    if (!canSeeSalary && ["payroll", "registry", "analytics", "clients", "contracts", "receivables", "expenses", "cashflow", "cash", "estimates", "leads", "budgets", "pnl", "vat", "fop_tax", "subpayments", "advances", "suppliers"].includes(t.page)) {
      setTweak("page", "profiles");
    }
  }, [role, t.page]);

  return (
    <div className={themeClass}>
      <div className="app app-with-header">
        <window.AppHeader
          page={t.page}
          setPage={(p) => setTweak("page", p)}
          theme={t.theme}
          setTheme={(th) => setTweak("theme", th)}
          role={role}
          setRole={(r) => setTweak("role", r)}
          counts={counts}
          user={liveUser}
          onLogout={window.API ? window.API.logout : null}
          onChangePassword={liveUser ? () => setShowPwd(true) : null}
          onNewTask={() => setNewTask({})}
        />

        <main className="main">
          {openProjectId ? (
            <window.ProjectWorkspace
              objId={openProjectId}
              tasks={tasks}
              role={role}
              onOpenTask={onOpenTask}
              onToggleTask={onToggle}
              onBack={() => setOpenProjectId(null)}
            />
          ) : openGoProjId ? (
            <window.ProjectGoWorkspace
              projId={openGoProjId}
              role={role}
              onBack={() => setOpenGoProjId(null)}
            />
          ) : (
          <React.Fragment>
          {/* ДАШБОРД */}
          {t.page === "dashboard" && <window.DashboardPage role={role} tasks={visTasks} onNewTask={() => setNewTask({})} user={liveUser} />}

          {/* РОБОТА */}
          {t.page === "today"   && <TodayPage   tasks={visTasks} onOpenTask={onOpenTask} onToggle={onToggle} />}
          {t.page === "week"    && <WeekPage    tasks={visTasks} onOpenTask={onOpenTask} onToggle={onToggle} />}
          {t.page === "kanban"  && <window.KanbanPage tasks={visTasks} onOpenTask={onOpenTask} onToggle={onToggle} setTasks={setTasks} onAddTask={(preset) => setNewTask(preset || {})} onNewVisit={() => setNewVisit({})} />}
          {t.page === "tree"    && <window.TreePage tasks={visTasks} onOpenTask={onOpenTask} onToggle={onToggle} onTaskPatch={onTaskPatch} role={role} />}
          {t.page === "objects" && <ObjectsPage tasks={visTasks} onOpenTask={onOpenTask} onToggle={onToggle} onOpenProject={(id) => setOpenProjectId(id)} />}
          {t.page === "projects" && <window.ProjectActivityPage role={role} onOpenProject={(id) => setOpenGoProjId(id)} />}
          {t.page === "admin"   && <AdminPage   tasks={visTasks} onOpenTask={onOpenTask} onToggle={onToggle} />}

          {/* ПЕРСОНАЛ */}
          {t.page === "profiles"   && <window.ProfilesPage  tasks={tasks} role={role} onPromote={onPromote} onCreateTasks={onCreateTasks} onGoToTasks={() => setTweak("page", "kanban")} />}
          {t.page === "qualifications" && <window.QualificationsPage role={role} />}
          {t.page === "kpi"        && <window.KpiPage       role={role} />}
          {t.page === "time"       && <window.TimePage      tasks={tasks} role={role} />}
          {t.page === "vacation"   && <window.VacationPage  role={role} />}
          {t.page === "documents"  && <window.DocumentsPage role={role} />}
          {t.page === "orders"     && <window.OrdersPage    role={role} />}
          {t.page === "onboarding" && <window.OnboardingPage role={role} />}
          {t.page === "training"   && <window.TrainingPage   role={role} />}

          {/* ФІНАНСИ */}
          {t.page === "clients"     && canSeeSalary && <window.ClientsPage     role={role} />}
          {t.page === "contracts"   && canSeeSalary && <window.ContractsPage   role={role} tasks={tasks} onCreateTasks={onCreateTasks} onGoToTasks={() => setTweak("page", "kanban")} />}
          {t.page === "receivables" && canSeeSalary && <window.ReceivablesPage role={role} />}
          {t.page === "expenses"    && canSeeSalary && <window.ExpensesPage    role={role} />}
          {t.page === "cashflow"    && canSeeSalary && <window.CashflowPage    role={role} />}
          {t.page === "cash"        && canSeeSalary && <window.CashRegisterPage role={role} />}
          {t.page === "estimates"   && canSeeSalary && <window.EstimatesPage   role={role} />}

          {/* ЗАРПЛАТА */}
          {t.page === "payroll"     && canSeeSalary && <PayrollWithAdvances role={role} />}
          {t.page === "registry"    && canSeeSalary && <window.RegistryPage  role={role} />}
          {t.page === "sick_pay"    && canSeeSalary && <window.SickPayPage role={role} />}
          {t.page === "bonus_pay"   && canSeeSalary && <window.BonusPayPage role={role} />}
          {t.page === "history"     && canSeeSalary && <window.SalaryHistoryPage role={role} />}
          {t.page === "analytics"   && canSeeSalary && <window.AnalyticsPage role={role} />}

          {/* ЗВІТИ */}
          {t.page === "internal_reports"    && canSeeSalary && <window.InternalReportsPage role={role} />}
          {t.page === "supervision_journal" && <window.SupervisionJournalPage role={role} />}
          {t.page === "completion_acts"     && canSeeSalary && <window.CompletionActsPage role={role} />}
          {t.page === "report_templates"    && <window.ReportTemplatesPage role={role} />}

          {/* СКЛАД */}
          {t.page === "assets"    && <window.WarehousePage role={role} />}
          {t.page === "inventory" && <window.InventoryPage role={role} />}

          {/* ДОЗВІЛЬНІ */}
          {t.page === "tu"   && <window.TuPage role={role} />}
          {t.page === "dsns" && <window.DsnsPage role={role} />}
          {t.page === "kep"  && <window.KepPage role={role} />}

          {/* ІНТЕГРАЦІЇ */}
          {t.page === "drive"    && <window.DrivePage role={role} />}
          {t.page === "calendar" && <window.IntegrationStubPage kind="calendar" />}
          {t.page === "diia"     && <window.IntegrationStubPage kind="diia" />}
          {t.page === "bank"     && <window.IntegrationStubPage kind="bank" />}
          {t.page === "edessb"   && <window.IntegrationStubPage kind="edessb" />}
          {t.page === "telegram" && <window.IntegrationStubPage kind="telegram" />}
          {t.page === "vchasno"  && <window.IntegrationStubPage kind="vchasno" />}
          {t.page === "prozorro" && <window.IntegrationStubPage kind="prozorro" />}
          {t.page === "tax"      && <window.IntegrationStubPage kind="tax" />}
          {t.page === "maps"     && <window.IntegrationStubPage kind="maps" />}
          {t.page === "ai"       && <window.IntegrationStubPage kind="ai" />}

          {/* ПРОДАЖІ */}
          {t.page === "leads"     && canSeeSalary && <window.LeadsPage role={role} />}
          {t.page === "suppliers" && canSeeSalary && <window.SuppliersPage role={role} />}
          {t.page === "materials" && canSeeSalary && <window.MaterialsPage role={role} />}

          {/* ФІНАНСИ — продовження */}
          {t.page === "budgets"     && canSeeSalary && <window.BudgetsPage role={role} tasks={tasks} />}
          {t.page === "pnl"         && canSeeSalary && <window.PnlPage role={role} />}
          {t.page === "vat"         && canSeeSalary && <window.VatPage role={role} />}
          {t.page === "fop_tax"     && canSeeSalary && <window.FopTaxPage role={role} />}
          {t.page === "subpayments" && canSeeSalary && <window.SubPaymentsPage role={role} />}
          {t.page === "advances"    && canSeeSalary && <window.AdvancesPage role={role} />}

          {/* НАЛАШТУВАННЯ */}
          {t.page === "roles"          && <window.RolesPage   role={role} />}
          {t.page === "company"        && <window.CompanyPage role={role} />}
          {t.page === "legal_changes"  && <window.LegalChangesPage role={role} />}
          {t.page === "task_templates" && <window.TemplatesPage role={role} setPage={(p) => setTweak("page", p)} />}
          {t.page === "templates" && <window.TemplatesPage role={role} setPage={(p) => setTweak("page", p)} />}
          {t.page === "contacts"  && <window.ContactsPage role={role} />}
          {t.page === "ngo_directory" && <window.NgoDirectoryPage role={role} />}
          {t.page === "audit"          && <window.AuditLogPage role={role} />}
          {t.page === "notifications"  && <window.NotificationsPage role={role} />}
          </React.Fragment>
          )}
        </main>
      </div>

      {drawerTask && <Drawer task={drawerTask} onClose={onCloseTask} onStatusChange={onStatusChange} onTaskPatch={onTaskPatch} onOpenProject={(id) => { setDrawerTask(null); setOpenProjectId(id); }} />}

      {newTask && <window.NewTaskModal preset={newTask} onClose={() => setNewTask(null)} onCreate={onCreateTask} onSwitchToVisit={() => { setNewTask(null); setNewVisit({}); }} />}

      {newVisit && <window.NewVisitModal preset={newVisit} onClose={() => setNewVisit(null)} onCreate={onCreateVisit} />}

      {showPwd && <window.ChangePasswordModal onClose={() => setShowPwd(false)} />}

      <Tweaks t={t} setTweak={setTweak} />
    </div>
  );
}

// ============ TWEAKS ПАНЕЛЬ ============
function Tweaks({ t, setTweak }) {
  return (
    <window.TweaksPanel title="Tweaks">
      <window.TweakSection label="Тема">
        <window.TweakRadio
          value={t.theme}
          onChange={(v) => setTweak("theme", v)}
          options={[
            { value: "light", label: "Світла" },
            { value: "dark",  label: "Темна" },
          ]}
        />
      </window.TweakSection>

      <window.TweakSection label="Роль (хто залогінений)">
        {(window.API && window.API.mode === "live")
          ? <div style={{fontSize: 12, color: "var(--ink-3)", lineHeight: 1.5}}>Роль визначається обліковим записом ({window.API.user ? window.API.user.role : "—"}). Вийдіть, щоб увійти під іншим користувачем.</div>
          : <window.TweakRadio
              value={t.role}
              onChange={(v) => setTweak("role", v)}
              options={[
                { value: "director",   label: "Директор" },
                { value: "deputy",     label: "Заступник директора" },
                { value: "accountant", label: "Бухгалтер" },
                { value: "employee",   label: "Працівник" },
              ]}
            />}
      </window.TweakSection>

      <window.TweakSection label="Густина">
        <window.TweakRadio
          value={t.density}
          onChange={(v) => setTweak("density", v)}
          options={[
            { value: "compact",  label: "Щільно" },
            { value: "normal",   label: "Норма" },
            { value: "spacious", label: "Вільно" },
          ]}
        />
      </window.TweakSection>
    </window.TweaksPanel>
  );
}

// ============ ЕКРАН ЗАВАНТАЖЕННЯ / ВХОДУ ============
function BootSplash() {
  return (
    <div className="auth-screen">
      <div className="auth-splash">
        <div className="auth-logo"><span className="ubp-erp">ERP</span> <span className="ubp-name">УКРБУДПРОЄКТ®</span></div>
        <div className="auth-spinner"></div>
        <div className="auth-splash-sub">Завантаження…</div>
      </div>
    </div>
  );
}

function LoginScreen({ onAuthed }) {
  const [email, setEmail] = React.useState("okravchenko@ukrbudproiekt.ua");
  const [password, setPassword] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  const submit = async (e) => {
    e.preventDefault();
    setBusy(true); setErr(null);
    try {
      await window.API.login(email.trim(), password);
      await window.API.afterLogin();
      onAuthed();
    } catch (ex) {
      setErr(ex && ex.status === 401 ? "Невірний email або пароль" : "Не вдалося увійти. Перевірте з'єднання.");
      setBusy(false);
    }
  };

  return (
    <div className="auth-screen">
      <form className="auth-card" onSubmit={submit}>
        <div className="auth-logo auth-logo-lg"><span className="ubp-erp">ERP</span> <span className="ubp-name">УКРБУДПРОЄКТ®</span></div>
        <div className="auth-title">Вхід до ERP</div>
        <div className="auth-sub">ТОВ «Укрбудпроєкт»</div>

        <label className="auth-label">Email</label>
        <input className="auth-input" type="email" value={email} onChange={e => setEmail(e.target.value)} autoFocus required />

        <label className="auth-label">Пароль</label>
        <input className="auth-input" type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder="••••••••" required />

        {err && <div className="auth-err">{err}</div>}

        <button className="btn btn-primary auth-submit" type="submit" disabled={busy}>
          {busy ? "Вхід…" : "Увійти"}
        </button>
        <div className="auth-hint">Демо-доступ: <code>demo1234</code> (директор)</div>
      </form>
    </div>
  );
}

function SetPasswordScreen({ onDone }) {
  const [pw, setPw] = React.useState("");
  const [pw2, setPw2] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const ok = pw.length >= 8 && pw === pw2;

  const submit = async (e) => {
    e.preventDefault();
    if (!ok) { setErr(pw.length < 8 ? "Пароль має містити щонайменше 8 символів" : "Паролі не збігаються"); return; }
    setBusy(true); setErr(null);
    try {
      if (window.API.setPassword) await window.API.setPassword(pw);
      onDone && onDone();
    } catch (ex) {
      setErr("Не вдалося зберегти пароль. Спробуйте ще раз.");
      setBusy(false);
    }
  };

  return (
    <div className="auth-screen">
      <form className="auth-card" onSubmit={submit}>
        <div className="auth-logo auth-logo-lg"><span className="ubp-erp">ERP</span> <span className="ubp-name">УКРБУДПРОЄКТ®</span></div>
        <div className="auth-title">Новий пароль</div>
        <div className="auth-sub">Перший вхід — придумай власний пароль</div>

        <label className="auth-label">Новий пароль</label>
        <input className="auth-input" type="password" value={pw} onChange={e => setPw(e.target.value)} placeholder="мінімум 8 символів" autoFocus required />

        <label className="auth-label">Повтори пароль</label>
        <input className="auth-input" type="password" value={pw2} onChange={e => setPw2(e.target.value)} placeholder="••••••••" required />

        <div className={"auth-pw-rule " + (pw.length >= 8 ? "is-ok" : "")}>
          <span className="auth-pw-dot"></span>щонайменше 8 символів
        </div>

        {err && <div className="auth-err">{err}</div>}

        <button className="btn btn-primary auth-submit" type="submit" disabled={busy}>
          {busy ? "Збереження…" : "Зберегти і увійти"}
        </button>
        <div className="auth-hint">Тимчасовий пароль із листа більше не знадобиться</div>
      </form>
    </div>
  );
}

// Самообслуговувана зміна пароля будь-коли (модалка з хедера) — поточний → новий.
function ChangePasswordModal({ onClose }) {
  const [cur, setCur] = React.useState("");
  const [pw, setPw] = React.useState("");
  const [pw2, setPw2] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  const submit = async (e) => {
    e.preventDefault();
    setErr(null);
    if (pw.length < 8) { setErr("Новий пароль — мінімум 8 символів"); return; }
    if (pw !== pw2) { setErr("Паролі не збігаються"); return; }
    if (pw === cur) { setErr("Новий пароль має відрізнятися від поточного"); return; }
    setBusy(true);
    try {
      await window.API.changePassword(cur, pw);
      onClose && onClose();
    } catch (ex) {
      setErr(ex && ex.data && ex.data.detail ? ex.data.detail
        : (ex && ex.status === 400 ? "Поточний пароль невірний" : "Не вдалося змінити пароль"));
      setBusy(false);
    }
  };

  return (
    <div className="drawer-overlay" onClick={onClose}>
      <form className="auth-card" style={{maxWidth: 420, margin: "8vh auto"}}
            onClick={e => e.stopPropagation()} onSubmit={submit}>
        <div className="auth-title">Зміна пароля</div>
        <div className="auth-sub">Оновіть пароль свого облікового запису</div>
        <label className="auth-label">Поточний пароль</label>
        <input className="auth-input" type="password" value={cur} onChange={e => setCur(e.target.value)} autoFocus required />
        <label className="auth-label">Новий пароль</label>
        <input className="auth-input" type="password" value={pw} onChange={e => setPw(e.target.value)} placeholder="мінімум 8 символів" required />
        <label className="auth-label">Повторіть новий пароль</label>
        <input className="auth-input" type="password" value={pw2} onChange={e => setPw2(e.target.value)} placeholder="••••••••" required />
        {err && <div className="auth-err">{err}</div>}
        <button className="btn btn-primary auth-submit" type="submit" disabled={busy}>
          {busy ? "Збереження…" : "Зберегти пароль"}
        </button>
        <button type="button" className="btn auth-submit" style={{marginTop: 8}} onClick={onClose} disabled={busy}>
          Скасувати
        </button>
      </form>
    </div>
  );
}
window.ChangePasswordModal = ChangePasswordModal;

function AuthGate() {
  const previewPasswd = (typeof location !== "undefined" && location.search.indexOf("passwd=1") !== -1);
  const [phase, setPhase] = React.useState(
    previewPasswd ? "passwd" :
    ((typeof location !== "undefined" && location.search.indexOf("login=1") !== -1) ? "login" : "boot")
  ); // boot | login | passwd | app
  const nextAfterAuth = () =>
    (window.API.user && window.API.user.mustChangePassword) ? "passwd" : "app";
  React.useEffect(() => {
    if (phase === "login" || phase === "passwd") return; // прев'ю екранів через ?login=1 / ?passwd=1
    let on = true;
    window.API.bootstrap().then(mode => {
      if (!on) return;
      setPhase(mode === "live" && window.API.needAuth ? "login" : nextAfterAuth());
    });
    const onUnauth = () => { if (on) setPhase("login"); };
    window.addEventListener("erp-unauth", onUnauth);
    return () => { on = false; window.removeEventListener("erp-unauth", onUnauth); };
  }, []);

  if (phase === "boot")   return <BootSplash />;
  if (phase === "login")  return <LoginScreen onAuthed={() => setPhase(nextAfterAuth())} />;
  if (phase === "passwd") return <SetPasswordScreen onDone={() => setPhase("app")} />;
  return <App />;
}

// Mount
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<AuthGate />);
