/* calc2-shares.jsx — доли в смете: клиент / исполнитель / прораб / компания (экономика Г1, спека 2026-10-25-economy-design.md).
   Панель SharesBar (только руководитель), ячейки ShareCells (строка, этап, фаза), исполнитель и свои % этапа StageShares,
   итог ShareTotal; LinesContext отдаёт строкам доли из одного расчёта дерева (worksTotals.byNode). Какие колонки видит роль — Calc2.shareCols(role); кто правит — Calc2.sharesEditable(role, status).
   Считает движок (Calc2.worksTotals / lineShares): здесь только вывод и правка est.economy. В печать доли не идут. */
(function () {
  const C = window.Calc2;
  const { useState, useRef } = React;
  /* доли всех строк сметы ({ id узла → доли }) одним расчётом на дерево; null — у роли нет колонок долей */
  const LinesContext = React.createContext(null);

  const MODES = [{ v: 'client', l: 'От цены клиента' }, { v: 'executor', l: 'От цены исполнителя' }];
  const COL_TITLE = { executor: 'Исполнителю', foreman: 'Прорабу', company: 'Компании' };
  const COL_NAME = { client: 'клиент', executor: 'исполнитель', foreman: 'прораб', company: 'компания' };
  const rub = (n) => C.rub(n || 0) + ' ₽';
  /* доля компании от клиента с десятой, если не целая: «29,5 %» (целое — «30 %»); движок хранит целый companyPct */
  const pctLabel = (company, client) => {
    const v = client > 0 ? Math.round((company / client) * 1000) / 10 : 0;
    return String(v).replace('.', ',') + ' %';
  };
  /* предупреждения о процентах: переполнение «от цены исполнителя» (прораб + компания ≥ 95) и минус компании «от цены клиента»
     (исполнитель + прораб > 100); p — результат Calc2.sharePct на нужном уровне */
  const OVERFLOW_NOTE = 'Прораб + компания ≥ 95 % — цены не пересчитаны';
  const OVER100_NOTE = 'Исполнитель + прораб > 100 %';
  function pctNote(eco, p) {
    if (!eco || !p) return null;
    if (p.overflow) return OVERFLOW_NOTE;
    if (eco.mode === 'client' && p.executor + p.foreman > 100) return OVER100_NOTE;
    return null;
  }

  /* процент 0…100: черновик, пока человек печатает; на blur или Enter уходит число, пусто — null (взять с уровня выше), Esc — отмена */
  function PctField({ value, placeholder, onCommit, disabled, label }) {
    const [draft, setDraft] = useState(null);
    const skip = useRef(false);
    const commit = () => {
      if (skip.current) { skip.current = false; setDraft(null); return; }
      if (draft == null) return;
      setDraft(null);
      const raw = draft.trim().replace(',', '.');
      if (raw === '') { if (value != null) onCommit(null); return; }
      const n = Number(raw);
      if (!isFinite(n)) return;
      const v = Math.min(100, Math.max(0, n));
      if (v !== value) onCommit(v);
    };
    return (
      <input type="text" inputMode="decimal" className="cc-share-in" aria-label={label} title={label} disabled={disabled} placeholder={placeholder}
        value={draft != null ? draft : (value == null ? '' : String(value).replace('.', ','))}
        onChange={(e) => setDraft(e.target.value.replace(/[^\d.,]/g, ''))} onBlur={commit}
        onKeyDown={(e) => {
          if (e.key === 'Enter') e.currentTarget.blur();
          else if (e.key === 'Escape') { skip.current = true; e.currentTarget.blur(); }
        }} />
    );
  }

  /* панель долей сметы — только у руководителя */
  function SharesBar({ est, setEst, role }) {
    if (role !== 'super') return null;
    const eco = C.economyOf(est);
    const edit = C.sharesEditable(role, est.status).pct;
    const locked = !edit && <span className="cc-share-note">Смета у клиента — доли не меняются</span>;
    if (!eco) {
      return (
        <div className="cc-shares-bar">
          <span className="cc-share-note">Доли выключены: исполнителю — себестоимость из каталога</span>
          <button type="button" className="cc-share-btn" disabled={!edit} onClick={() => setEst(C.enableEconomy(est, true))}>Включить доли</button>
          {locked}
        </div>
      );
    }
    const sp = C.sharePct(est, null);
    // уровень сметы, а затем этапы со своими процентами или исполнителем: у них проценты могут переполниться отдельно
    const note = pctNote(eco, sp) || Object.keys(eco.stages).map((id) => pctNote(eco, C.sharePct(est, id))).find(Boolean) || null;
    const field = (key, label) => (
      <label className="cc-share-fld" key={key}>
        <span>{label}</span>
        <PctField value={eco.pct[key]} placeholder={String(sp[key])} label={label} disabled={!edit} onCommit={(n) => setEst(C.setEconomy(est, { [key]: n }))} />
        <span>%</span>
      </label>
    );
    return (
      <div className="cc-shares-bar">
        <span className="cc-shares-seg" role="group">
          {MODES.map((m) => (
            <button key={m.v} type="button" className={eco.mode === m.v ? 'on' : ''} disabled={!edit} onClick={() => setEst(C.setEconomy(est, { mode: m.v }))}>{m.l}</button>
          ))}
        </span>
        {eco.mode === 'client' && field('executor', 'Исполнителю')}
        {field('foreman', 'Прорабу')}
        {eco.mode === 'executor' && field('company', 'Компании')}
        <button type="button" className="cc-share-btn" disabled={!edit} onClick={() => setEst(C.enableEconomy(est, false))}>Выключить доли</button>
        {note && <span className="cc-share-note warn">{note}</span>}
        {locked}
      </div>
    );
  }

  /* ячейки долей: по одной на колонку роли, кроме клиента; t = { executor, foreman, company, companyPct } */
  function ShareCells({ t, role }) {
    const cols = C.shareCols(role);
    if (!t || cols.length <= 1) return null;
    return (
      <React.Fragment>
        {cols.filter((c) => c !== 'client').map((c) => (
          <span key={c} className={'cc-share cc-share--' + c} title={c === 'company' ? pctLabel(t.company, t.client) + ' от клиента' : COL_TITLE[c]}>{rub(t[c])}</span>
        ))}
      </React.Fragment>
    );
  }

  /* этап: исполнитель (список или имя), свои проценты этапа (руководитель) и доли этапа */
  function StageShares({ est, setEst, role, stage, shares, view, executors }) {
    const [open, setOpen] = useState(false);
    const cols = C.shareCols(role);
    const eco = C.economyOf(est);
    const ed = C.sharesEditable(role, est.status);
    const exId = C.stageExecutor(est, stage.id);
    const own = eco && eco.stages[stage.id] && eco.stages[stage.id].pct;
    const Vis = view && window.HierarchyVis ? window.HierarchyVis : null;
    const cells = <ShareCells t={shares} role={role} />;
    let exec = null;
    if (eco && ed.executor && executors) {
      const people = executors.filter((p) => p.status !== 'left' || p.id === exId);
      exec = (
        <select className="cc-stage-exec" value={exId || ''} aria-label="Исполнитель этапа" onChange={(e) => setEst(C.setStageEconomy(est, stage.id, { executorId: e.target.value || null }))}>
          <option value="">исполнитель не выбран</option>
          {people.map((p) => <option key={p.id} value={p.id}>{p.name}</option>)}
        </select>
      );
    } else if (eco && cols.indexOf('executor') >= 0) {
      const p = exId && executors ? executors.find((x) => x.id === exId) : null;
      exec = <span className="cc-stage-exec">{p ? p.name : 'исполнитель не выбран'}</span>;
    }
    const pctBtn = eco && role === 'super' ? (
      <button type="button" className={'cc-share-btn cc-share-btn--sm' + (open ? ' on' : '')} title="Проценты этапа" onClick={() => setOpen(!open)}>%{own ? ' · свои %' : ''}</button>
    ) : null;
    const note = cols.indexOf('company') >= 0 ? pctNote(eco, C.sharePct(est, stage.id)) : null;
    return (
      <span className="cc-stage-sh" onClick={(e) => e.stopPropagation()}>
        {exec}
        {pctBtn}
        {note && <span className="cc-share-note warn">{note}</span>}
        {Vis ? <Vis view={view} field="cost" inline>{cells}</Vis> : cells}
        {open && pctBtn && (
          <span className="cc-stage-pct">
            {['executor', 'foreman', 'company'].map((k) => (
              <label className="cc-share-fld" key={k}>
                <span>{COL_TITLE[k]}</span>
                <PctField value={own ? own[k] : null} placeholder="от сметы" label={COL_TITLE[k]} disabled={!ed.pct}
                  onCommit={(n) => setEst(C.setStageEconomy(est, stage.id, { [k]: n }))} />
                <span>%</span>
              </label>
            ))}
          </span>
        )}
      </span>
    );
  }

  /* итог сметы под деревом: клиент и видимые роли колонки; у компании ещё доля от клиента */
  function ShareTotal({ w, role }) {
    const cols = C.shareCols(role);
    if (!w || cols.length <= 1) return null;
    return (
      <div className="cc-shares-total">
        <b>Итого</b>
        {cols.map((c) => (
          <span key={c} className="cc-share-sum">
            {COL_NAME[c]} <b>{rub(c === 'client' ? w.client : w[c])}</b>{c === 'company' ? ' (' + pctLabel(w.company, w.client) + ')' : ''}
          </span>
        ))}
      </div>
    );
  }

  window.Calc2Shares = { SharesBar, ShareCells, StageShares, ShareTotal, LinesContext };
})();
