/* ctor-v2.jsx — облик «Конструктора проектов» как у кабинетов клиента и прораба (DESIGN.md v1.3, KSH-470).
   CtorWindow — раздел окном на весь экран поверх главной (тип «Окно на весь экран» из DESIGN.md §6: отступ 24, радиус 36 сверху).
   Без transform: старые диалоги, выпадашки и поповеры панелей (position: fixed) встают поверх окна, как раньше поверх страницы.
   CtorHome — главная Конструктора: приветствие, поиск, серая сводка каталога, «Проверка каталога», «Изменения» (черновик, заявки, публикации),
   «Шаблоны смет и автоправила», «Условия новых смет», «Путь сделки до сметы» (окно — ctor-path.jsx) и «Фазы каталога». Данные считает constructor/ctor-home.js из того, что уже есть на странице;
   блоки — из библиотеки виджетов (window.LKW).
   Префикс c2, чтобы не пересекаться с другими ctor-*.jsx (общий top-level scope). Exports on window: CtorWindow, CtorHome. */
const { useEffect: c2UseEffect, useRef: c2UseRef } = React;

const C2_OVERLAYS = '[role="dialog"]:not(.c2-win), .c2-nav ul';
function c2Today() {
  const s = new Date().toLocaleDateString('ru-RU', { weekday: 'long', day: 'numeric', month: 'long' });
  return s.charAt(0).toUpperCase() + s.slice(1);
}
function c2Greeting() {
  const h = new Date().getHours();
  return h < 5 ? 'Доброй ночи' : h < 12 ? 'Доброе утро' : h < 18 ? 'Добрый день' : 'Добрый вечер';
}
const c2Plural = (n, a, b, c) => { const m = Math.abs(n) % 100, k = m % 10; return m > 10 && m < 20 ? c : k > 1 && k < 5 ? b : k === 1 ? a : c; };

/* ============ CtorWindow — раздел поверх главной ============
   Esc закрывает, только если курсор не в поле ввода и поверх нет своего диалога панели — иначе пропал бы набранный текст */
function CtorWindow({ eyebrow, title, actions, tabs, onClose, children }) {
  const ref = c2UseRef(null);
  c2UseEffect(() => {
    const k = (e) => {
      if (e.key !== 'Escape' || e.defaultPrevented) return;
      const t = e.target;
      if (t && (t.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName))) return;
      if (document.querySelector(C2_OVERLAYS)) return;
      onClose();
    };
    document.addEventListener('keydown', k);
    document.documentElement.classList.add('c2-locked');
    return () => { document.removeEventListener('keydown', k); document.documentElement.classList.remove('c2-locked'); };
  }, [onClose]);
  c2UseEffect(() => { if (ref.current) ref.current.focus(); }, [title]);
  return (
    <React.Fragment>
      <div className="c2-scrim" onClick={onClose} />
      <div className="c2-win" role="dialog" aria-modal="true" aria-label={title} tabIndex={-1} ref={ref}>
        <div className="c2-whead">
          <div className="c2-wtitle">{eyebrow ? <div className="c2-eyebrow">{eyebrow}</div> : null}<h1 className="c2-h1">{title}</h1></div>
          <div className="c2-wact">{actions}<button type="button" className="c2-x" aria-label="Закрыть — на главную Конструктора" onClick={onClose}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" /></svg>
          </button></div>
        </div>
        {tabs}
        <div className="c2-wbody">{children}</div>
      </div>
    </React.Fragment>);
}

/* ============ CtorHome — главная Конструктора ============
   home — CtorHomeData.build(...) (constructor/ctor-home.js): факты, проверка каталога, шаблоны и автоправила, условия новых смет, фазы, публикации.
   drafts — CtorDrafts.summary() по правам человека; reviews/proposals — очередь руководителя; mine — свои заявки (вернул / на согласовании).
   onGo(sectionId) открывает раздел, canGo(sectionId) — есть ли он в меню человека; onOpenUnit(unit) — первый пункт меню этого unit. */
const C2_CHECK_IC = { warn: 'alert', info: 'doc', ok: 'check' };

/* строки как в «Согласованиях» клиента, но строка может быть тихой (is-ok: в порядке — серым) и без перехода */
function C2Rows({ id, title, n, rows, empty, foot, className }) {
  const W = window.LKW;
  return (
    <section className={'cv-w cv-apr-w lw-rows c2-rows' + (className ? ' ' + className : '')} aria-labelledby={id}>
      <W.WHead id={id} title={title} n={n} />
      {rows.length === 0
        ? <div className="note-s" style={{ marginTop: 14 }}><W.Ic n="check" c="#2F5D3A" s={16} /><span>{empty}</span></div>
        : <div className="rows">{rows.map((r) => {
          const body = <React.Fragment><span className="tx"><span className="t">{r.title}</span><span className="lab">{r.sub}</span></span>
            {r.right ? <span className="by"><b>{r.right}</b></span> : null}</React.Fragment>;
          return (
            <div key={r.key} className={'r lw-r' + (r.cls ? ' ' + r.cls : '')}>
              <span className="ic"><W.Ic n={r.ic || 'check'} s={15} /></span>
              {r.onClick ? <button type="button" className="c2-rb" onClick={r.onClick}>{body}</button> : <span className="c2-rb">{body}</span>}
            </div>);
        })}</div>}
      {foot ? <div className="ft">{foot}</div> : null}
    </section>);
}

function CtorHome({ name, search, home, version, drafts, changeCount, canPublish, onPublish, proposeCount, onPropose,
  reviews, proposals, onReview, onProposals, returned, waiting, onGo, canGo, onOpenUnit }) {
  const W = window.LKW;
  const can = (id) => !canGo || canGo(id);
  const go = (id) => (can(id) ? () => onGo(id) : undefined);
  const facts = home.facts.map((f) => ({ v: f.v, lab: f.lab, onClick: go(f.go) }));
  const live = <span className="now"><span>Опубликована версия {version}{changeCount > 0 ? ' · в черновике ' + changeCount + ' ' + c2Plural(changeCount, 'изменение', 'изменения', 'изменений') : ' · черновик пуст'}</span></span>;
  const fmtAt = (at) => new Date(at).toLocaleString('ru-RU', { day: 'numeric', month: 'long', hour: '2-digit', minute: '2-digit' });
  const fmtDay = (at) => new Date(at).toLocaleDateString('ru-RU', { day: 'numeric', month: 'long' });
  const warn = home.checks.filter((c) => c.state === 'warn').length;
  const checkRows = home.checks.map((c) => ({ key: c.id, ic: C2_CHECK_IC[c.state], cls: 'is-' + c.state, title: c.title, sub: c.sub, right: c.right, onClick: go(c.go) }));
  // изменения: черновик, заявки и предложения, свои заявки, затем последние публикации (тихо)
  const pending = [].concat(
    drafts.map((s) => ({ key: 'd' + s.id, ic: 'doc', title: s.label, sub: 'Черновик · ' + s.changes + ' ' + c2Plural(s.changes, 'изменение', 'изменения', 'изменений'), onClick: () => onOpenUnit(s.id) })),
    reviews.map((e) => ({ key: 'r' + e.id, ic: 'check', title: (e.who || 'Сотрудник') + ' · ' + e.sections.map((s) => s.label).join(', '), sub: 'Заявка на публикацию · ' + fmtAt(e.at), onClick: onReview })),
    proposals.map((p) => ({ key: 'p' + p.id, ic: 'tool', title: p.name, sub: 'Предложение работы' + (p.executorName ? ' · ' + p.executorName : '') + (p.stageName ? ' · ' + p.stageName : ''), onClick: onProposals })),
    returned.map((e) => ({ key: 'b' + e.id, ic: 'back', title: 'Вернул руководитель' + (e.resolvedBy ? ' (' + e.resolvedBy + ')' : '') + ': ' + (e.resolvedComment || 'без комментария'), sub: e.sections.map((s) => s.label).join(', '), onClick: () => onOpenUnit(e.sections[0] && e.sections[0].id) })),
    waiting.map((e) => ({ key: 'w' + e.id, ic: 'clock', title: 'На согласовании у руководителя', sub: e.sections.map((s) => s.label).join(', ') + ' · ' + fmtAt(e.at) })));
  const published = home.history.map((h) => ({ key: 'h' + h.id, ic: 'clock', cls: 'is-ok', title: 'Версия ' + h.version + ' · ' + h.who, sub: (h.comment ? h.comment + ' · ' : '') + (h.sections.join(', ') || 'без разделов'), right: fmtDay(h.at) }));
  // нет ни черновика, ни заявок, ни публикаций — блока «Изменения» нет (это уже сказано в серой полосе), проверка на всю ширину
  const changeRows = pending.concat(published);
  const wide = changeRows.length === 0;
  const changeBtns = (canPublish || proposeCount > 0) && (drafts.length > 0 || reviews.length > 0) ? <React.Fragment>
    {proposeCount > 0 && <button type="button" className="lw-btn-l" onClick={onPropose}>На согласование ({proposeCount})</button>}
    {canPublish && <button type="button" className="lw-btn-k" onClick={onPublish}>Опубликовать</button>}
  </React.Fragment> : null;
  const tplRows = home.templates.map((t) => ({ key: t.id, ic: t.id === 'packages' ? 'box' : t.id === 'rules' ? 'tool' : 'doc', title: t.title, sub: t.sub, right: t.right, onClick: go(t.go) }));
  // «Путь сделки до сметы» (ctor-path.jsx): окно открыто — id стадии ('' — первая), закрыто — null; адрес #path=<стадия>
  const [pathAt, setPathAt] = React.useState(() => (home.path && window.cdpReadHash ? window.cdpReadHash() : null));
  const [pathDp, setPathDp] = React.useState(true);
  const openPath = (id) => { setPathAt(id); window.cdpWriteHash(id); };
  const closePath = () => { setPathAt(null); window.cdpWriteHash(null); };
  return (
    <div className="c2-home">
      <section className="c2-hero">
        <div>
          <p className="c2-eyebrow">{c2Today()}</p>
          <h1 className="c2-display">{c2Greeting()}{name ? ', ' + name : ''}</h1>
          <p className="c2-lead">Мастер-каталог ОБИТЕЛЬ: работы и цены, материалы, шаблоны смет и правила, из которых собирается каждая смета.</p>
        </div>
        {search ? <div className="c2-search">{search}</div> : null}
      </section>
      {W && <W.FactsBand live={live} facts={facts} label="Каталог" />}
      {W && <div className="c2-grid">
        <div className={wide ? 'c2-w-12' : 'c2-w-7'}><C2Rows id="c2-checks" title="Проверка каталога" n={warn} rows={checkRows} empty="Проверять пока нечего" className={'c2-checks' + (wide ? ' is-wide' : '')} /></div>
        {!wide && <div className="c2-w-5"><C2Rows id="c2-changes" title="Изменения" n={pending.length} rows={changeRows} empty="" className="c2-changes" foot={changeBtns} /></div>}
        <div className="c2-w-6"><C2Rows id="c2-tpl" title="Шаблоны смет и автоправила" rows={tplRows} empty="Шаблонов пока нет" /></div>
        <div className="c2-w-6">
          <section className="cv-w cv-apr-w c2-terms" aria-labelledby="c2-terms-h">
            <W.WHead id="c2-terms-h" title="Условия новых смет" />
            <dl className="c2-dl">{home.terms.map((t) => (
              <div key={t.id} className="c2-dr">
                <dt>{t.k}</dt>
                <dd>{can(t.go) ? <button type="button" className="c2-rb" onClick={() => onGo(t.go)}>{t.v}</button> : t.v}</dd>
              </div>))}</dl>
          </section>
        </div>
        {home.path && window.CtorPathCard && <div className="c2-w-12"><window.CtorPathCard path={home.path} onOpen={openPath} /></div>}
        <div className="c2-w-12">
          <section className="cv-w c2-phases" aria-labelledby="c2-ph-h">
            <W.WHead id="c2-ph-h" title="Фазы каталога" text={can('works') ? 'Все работы' : undefined} onOpen={go('works')} />
            <ol className="c2-chain" style={{ gridTemplateColumns: 'repeat(' + home.phases.length + ', minmax(0, 1fr))' }}>{home.phases.map((p) => (
              <li key={p.id}>
                <button type="button" className="c2-rb" onClick={go('works')} disabled={!can('works')}>
                  <span className="c2-pn">Фаза {p.idx}</span>
                  <span className="c2-pt">{p.name}</span>
                  <span className="c2-pbar" aria-hidden="true"><i style={{ width: Math.max(4, Math.round(p.share * 100)) + '%' }} /></span>
                  <span className="c2-ps">{p.stages} {c2Plural(p.stages, 'этап', 'этапа', 'этапов')} · {p.works} {c2Plural(p.works, 'работа', 'работы', 'работ')}</span>
                </button>
              </li>))}</ol>
          </section>
        </div>
      </div>}
      {pathAt != null && home.path && window.CtorPathModal && <window.CtorPathModal path={home.path} at={pathAt} design={pathDp} onDesign={setPathDp}
        onAt={openPath} onClose={closePath} onGo={onGo} canGo={canGo} />}
    </div>);
}

Object.assign(window, { CtorWindow, CtorHome });
