/* calc2-schedule.jsx — детальный график сметы (иерархический Гант).
   Этап → задачи (параллельные дорожки по дисциплине) → подзадачи.
   Бары задач раскрашены по роли-исполнителю; параллельные дорожки видно по смещению.
   Материалы с lead-time дают маркер «заказать до». Менеджер/Прораб/Super фиксируют старт. */
(function () {
  const C = window.Calc2;
  const { Ic } = window;
  const { useState } = React;

  function roleColor(roleId) { const r = C.roleInfo(roleId); return r ? r.color : 'var(--c-subtle)'; }
  function roleName(roleId) { const r = C.roleInfo(roleId); return r ? r.name : 'Общая бригада'; }

  function ScheduleView({ est, setEst, role, catalog }) {
    const [editPin, setEditPin] = useState(null);
    const [open, setOpen] = useState({});   // раскрытые этапы
    const [openTask, setOpenTask] = useState({});
    const [showMat, setShowMat] = useState(true);
    const sched = C.computeSchedule(est, catalog);
    const canPin = role === 'manager' || role === 'super' || role === 'foreman';

    if (!sched.stages.length) {
      return <div className="cc-empty"><Ic n="calendar-range" s={26} c="var(--text-tertiary)" /><div style={{ marginTop: 10 }}>Включите работы — график построится автоматически.</div></div>;
    }

    const start = sched.projStart.getTime();
    const finish = sched.projFinish.getTime();
    const span = Math.max(1, finish - start);
    const pct = (t) => ((t - start) / span) * 100;
    const wpct = (a, b) => Math.max(1.2, pct(b) - pct(a));

    // дисциплины проекта (для легенды)
    const discSet = {};
    sched.stages.forEach((st) => st.tasks.forEach((t) => { discSet[t.role] = 1; }));
    const discList = Object.keys(discSet);

    // недельные засечки (адаптивная плотность подписей)
    const ticks = []; const d = new Date(sched.projStart); d.setHours(0, 0, 0, 0);
    let guard = 0;
    while (d.getTime() <= finish && guard < 80) { ticks.push(new Date(d)); d.setDate(d.getDate() + 7); guard++; }
    const labelEvery = ticks.length > 30 ? 4 : ticks.length > 16 ? 2 : 1;

    const setStart = (id, iso) => { setEst(C.withPin(est, id, iso || null)); setEditPin(null); };
    const toggle = (id) => setOpen((o) => ({ ...o, [id]: !o[id] }));
    const toggleTask = (id) => setOpenTask((o) => ({ ...o, [id]: !o[id] }));
    const parallelStages = sched.stages.filter((s) => s.laneCount > 1).length;

    const Bar = ({ a, b, color, label, faded, thin }) => (
      <div className="cc-g-bar" style={{ left: pct(a.getTime()) + '%', width: wpct(a, b) + '%', background: color, opacity: faded ? 0.5 : 1, height: thin ? 12 : 18 }}>
        {label && <span className="bd">{label}</span>}
      </div>
    );
    const MatMarks = ({ mats }) => showMat ? mats.map((m, i) => (
      <span key={i} className="cc-g-mat" style={{ left: pct(m.orderBy.getTime()) + '%', background: m.kind === 'finish' ? 'var(--primary)' : 'var(--text-tertiary)' }}
        title={'Заказать «' + m.name + '» до ' + C.fmtDate(m.orderBy) + (m.lead ? ' · поставка ' + m.lead + 'д' : '') + (m.approval ? ' · треб. согл.' : '')}>
        <Ic n={m.approval ? 'alert-triangle' : 'package'} s={9} c="#fff" />
      </span>
    )) : null;

    return (
      <div>
        <div className="cc-kpis" style={{ marginBottom: 14 }}>
          <div className="cc-kpi"><i>Старт</i><b>{C.fmtDate(sched.projStart)}</b><u>первый этап</u></div>
          <div className="cc-kpi"><i>Финиш</i><b>{C.fmtDate(sched.projFinish)}</b><u>по критическому пути</u></div>
          <div className="cc-kpi"><i>Срок</i><b>{sched.calTotal} дн</b><u>≈ {sched.weeks} нед</u></div>
          <div className="cc-kpi accent"><i>Экономия ∥</i><b>{sched.savedDays} дн</b><u>{parallelStages} эт. с параллельными работами</u></div>
        </div>

        <div className="cc-g-toolbar">
          <div className="cc-g-legend">
            {discList.map((id) => <span key={id} className="cc-g-leg"><span className="dot" style={{ background: roleColor(id) }} />{roleName(id)}</span>)}
          </div>
          <div className="cc-g-controls">
            <button className={'cc-g-toggle' + (showMat ? ' on' : '')} onClick={() => setShowMat((v) => !v)} title="Маркеры закупки материалов"><Ic n="package" s={13} />Закупки</button>
            <button className="cc-g-toggle" onClick={() => setOpen(Object.fromEntries(sched.stages.map((s) => [s.id, true])))}><Ic n="unfold-vertical" s={13} />Развернуть всё</button>
            <button className="cc-g-toggle" onClick={() => { setOpen({}); setOpenTask({}); }}><Ic n="fold-vertical" s={13} />Свернуть</button>
          </div>
        </div>

        <div className="cc-gantt">
          <div className="cc-gantt-head">
            <div className="lbl">Этап · задача · подзадача</div>
            <div className="cc-gantt-scale">
              {ticks.map((tk, i) => <span key={i} className={'cc-gantt-tick' + (i % labelEvery ? ' nolabel' : '')} style={{ left: pct(tk.getTime()) + '%' }}>{i % labelEvery ? '' : C.fmtDate(tk)}</span>)}
            </div>
          </div>

          {sched.stages.map((st) => {
            const isOpen = !!open[st.id];
            return (
              <React.Fragment key={st.id}>
                {/* ── СТРОКА ЭТАПА ── */}
                <div className={'cc-gantt-row stage' + (st.virtual ? ' virtual' : '')} onClick={(e) => { if (e.target.closest('input,.cc-gantt-pin')) return; toggle(st.id); }}>
                  <div className="cc-gantt-lbl">
                    <button className={'cc-g-chev' + (isOpen ? ' open' : '')}><Ic n="chevron-right" s={14} /></button>
                    <span className="dot" style={{ background: st.color }} />
                    {st.virtual && <span className="cc-pkg-mark sm" style={{ background: st.color }} title="Шаги пакетов услуг">📦</span>}
                    <span className="nm" title={st.phase + ' › ' + (st.virtual ? 'пакеты · ' : '') + st.name}>{st.name}</span>
                    {st.laneCount > 1 && <span className="cc-g-par" title={st.laneCount + ' параллельные дорожки'}>∥{st.laneCount}</span>}
                    {canPin && (
                      editPin === st.id ? (
                        <input type="date" autoFocus defaultValue={C.toISO(st.start)} className="cc-disc" style={{ width: 128 }}
                          onClick={(e) => e.stopPropagation()}
                          onBlur={(e) => setStart(st.id, e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') setStart(st.id, e.target.value); if (e.key === 'Escape') setEditPin(null); }} />
                      ) : (
                        <span className={'cc-gantt-pin' + (st.pinned ? ' on' : '')} title={st.pinned ? 'Дата зафиксирована' : 'Зафиксировать старт'} onClick={(e) => { e.stopPropagation(); setEditPin(st.id); }}><Ic n={st.pinned ? 'pin' : 'pin-off'} s={12} /></span>
                      )
                    )}
                  </div>
                  <div className="cc-gantt-track">
                    <Bar a={st.start} b={st.end} color={st.color} label={st.workdays + ' дн'} />
                    {st.pause > 0 && <div className="cc-gantt-pause" style={{ left: pct(st.end.getTime()) + '%', width: (st.pause * 86400000 / span) * 100 + '%' }} title={'Технологический простой ' + st.pause + ' дн'} />}
                  </div>
                </div>

                {/* ── ЗАДАЧИ ── */}
                {isOpen && st.tasks.map((t) => {
                  const tOpen = !!openTask[t.id];
                  const hasSubs = t.subs && t.subs.length;
                  return (
                    <React.Fragment key={t.id}>
                      <div className="cc-gantt-row task" onClick={(e) => { if (!hasSubs) return; toggleTask(t.id); }}>
                        <div className="cc-gantt-lbl" style={{ paddingLeft: 30 }}>
                          {hasSubs ? <button className={'cc-g-chev sm' + (tOpen ? ' open' : '')}><Ic n="chevron-right" s={12} /></button> : <span style={{ width: 14 }} />}
                          <span className="dot sm" style={{ background: roleColor(t.role) }} />
                          {t.pkg && <span className="cc-line-pkg" style={{ color: t.pkg.color }} title={t.pkg.name}>{t.pkg.icon}</span>}
                          <span className="nm task" title={t.name}>{t.name}</span>
                          {t.lane > 0 && <span className="cc-g-lane" title="Параллельная дорожка">∥</span>}
                          {showMat && t.mats.length > 0 && <span className="cc-g-matn" title={t.mats.length + ' материалов с закупкой'}><Ic n="package" s={10} />{t.mats.length}</span>}
                        </div>
                        <div className="cc-gantt-track">
                          <Bar a={t.start} b={t.end} color={roleColor(t.role)} label={t.workdays + 'д'} thin />
                          <MatMarks mats={t.mats} />
                        </div>
                      </div>
                      {/* ── ПОДЗАДАЧИ ── */}
                      {tOpen && hasSubs && t.subs.map((su) => (
                        <div className="cc-gantt-row sub" key={su.id}>
                          <div className="cc-gantt-lbl" style={{ paddingLeft: 56 }}>
                            <span className="dot xs" style={{ background: roleColor(su.role) }} />
                            <span className="nm sub" title={su.name}>{su.name}</span>
                          </div>
                          <div className="cc-gantt-track">
                            <Bar a={su.start} b={su.end} color={roleColor(su.role)} faded thin label={su.workdays + 'д'} />
                          </div>
                        </div>
                      ))}
                    </React.Fragment>
                  );
                })}
              </React.Fragment>
            );
          })}
        </div>

        <div className="cc-g-foot">
          <span><span className="cc-g-mat static"><Ic n="package" s={9} c="#fff" /></span> «заказать до» — старт работ минус срок поставки материала</span>
          <span><span className="cc-g-mat static warn"><Ic n="alert-triangle" s={9} c="#fff" /></span> требует согласования клиента</span>
          <span>штриховка — технологический простой (сушка/усадка)</span>
          <span>∥ — параллельная дорожка (другая дисциплина, идёт одновременно)</span>
          {!canPin && <span>фиксация дат — у менеджера и прораба</span>}
        </div>
      </div>
    );
  }

  window.ScheduleView = ScheduleView;
})();
