/* lk-spec.jsx — «Спецификация» объекта, связанная с графиком работ (Роман, 07.11.2026, шаг 1 плана).
   Материалы сметы и позиции «покупает клиент» из спецификации ДП одной таблицей по этапам графика: для каждой позиции —
   «решить до» (если нужно согласование), «заказать до», «привезти к» = старт этапа, статус и доставка. Этап с просроченным
   решением, заказом или без материала на объекте помечен «под угрозой» — это предупреждение, этап не блокируется
   (решение Романа «Предупреждать»); заказать несогласованную чистовую позицию стор не даст (specGate).
   Данные — ProjectStore.views.projectSpec(p). Шаг 3–4: версия позиции и комментарий клиента к правкам; из строк — «Создать доставку»
   (выбранные незаказанные позиции → своя заявка на дату, onDelivery) и события объекта (onEvent): «Замер → изготовление → монтаж»,
   «Сборка / монтаж», «Клиент везёт сам» — они ложатся в «События на объекте» графика. Согласует клиент в своём кабинете, заказывает закупщик.
   Exports on window: LKW.SpecW (дописывает в библиотеку lk-widgets.jsx, грузится после неё). */
(function () {
  'use strict';
  const W = window.LKW;
  const { Modal, CalTabs, rub, plural, dateR, cap } = W;
  const num = (x) => Math.round((+x || 0) * 100) / 100;
  const qty = (n, u) => num(n).toLocaleString('ru-RU') + (u ? ' ' + u : '');
  const d = (x) => (x ? dateR(x, { month: 'short' }) : '—');
  const PROC_L = { planned: 'не заказано', ordered: 'заказано', in_transit: 'в пути', on_site: 'на объекте', installed: 'смонтировано', partial: 'частично', delayed: 'задержка', waived: 'не нужно',
    select: 'клиент выбирает', approved: 'клиент выбрал', delivered: 'клиент привёз' };
  const WHY_L = { decide: 'не согласовано', order: 'не заказано', deliver: 'нет на объекте' };
  const status = (r) => (r.approval === 'pending' ? ['ждёт согласования', 'lw-spst is-ask'] : r.approval === 'rejected' ? ['правки', 'lw-spst is-ask']
    : [(r.buyer === 'client' && r.proc === 'ordered' ? 'клиент заказал' : PROC_L[r.proc] || r.proc), 'lw-spst' + (r.onSite ? ' is-on' : r.ordered ? ' is-ord' : '')]);
  // срок в ячейке: красный — прошёл и не сделано, охра — до срока неделя
  const due = (r, kind, date) => { const x = r.risks.find((y) => y.kind === kind); return <span className={'lw-spd' + (x ? ' is-' + x.level : '')}>{d(date)}</span>; };

  const EV_KINDS = [['make', 'Замер → изготовление → монтаж'], ['assembly', 'Сборка / монтаж'], ['client', 'Клиент везёт сам']];
  // форма события под строкой: вид, даты (у «замер → монтаж» — две), сохранить
  function EvForm({ r, t0, onSave, onCancel }) {
    const kinds = EV_KINDS.filter(([k]) => (k === 'client') === (r.buyer === 'client') || k === 'assembly');
    const [f, setF] = React.useState({ kind: kinds[0][0], date: t0 || '', end: '' });
    const [err, setErr] = React.useState('');
    const save = () => { const res = onSave({ kind: f.kind, rowId: r.id, name: r.name, date: f.date, end: f.end }) || {}; if (res.error) setErr(res.error); else onCancel(); };
    return (
      <div className="lw-spev">
        <select value={f.kind} onChange={(e) => setF({ ...f, kind: e.target.value })} aria-label="Какое событие">{kinds.map(([k, l]) => <option key={k} value={k}>{l}</option>)}</select>
        <label><span className="lab">{f.kind === 'make' ? 'Замер' : f.kind === 'client' ? 'Привезёт' : 'С'}</span><input type="date" value={f.date} onChange={(e) => setF({ ...f, date: e.target.value })} /></label>
        {f.kind !== 'client' && <label><span className="lab">{f.kind === 'make' ? 'Монтаж' : 'По'}</span><input type="date" value={f.end} onChange={(e) => setF({ ...f, end: e.target.value })} /></label>}
        <button type="button" className="lw-btn-l" onClick={onCancel}>Отмена</button>
        <button type="button" className="lw-btn-k" disabled={!f.date || (f.kind === 'make' && !f.end)} onClick={save}>На график</button>
        {err ? <span className="lw-spev-e">{err}</span> : null}
      </div>);
  }

  function SpecW({ p, s, t0, close, onSupply, onDelivery, onEvent }) {
    const [tab, setTab] = React.useState('all');
    const [sel, setSel] = React.useState([]);
    const [dlDate, setDlDate] = React.useState('');
    const [ev, setEv] = React.useState(null);
    const [msg, setMsg] = React.useState('');
    const canSel = (r) => !!onDelivery && r.buyer === 'us' && !r.ordered && !r.onSite;
    const toggleSel = (id) => setSel(sel.includes(id) ? sel.filter((x) => x !== id) : sel.concat([id]));
    const makeDl = () => { const res = onDelivery(sel, dlDate) || {}; if (res.error) setMsg(res.error); else { setMsg('Доставка на ' + d(dlDate) + ' создана: ' + sel.length + ' ' + plural(sel.length, 'позиция', 'позиции', 'позиций') + '. Закупщик закажет, клиент подтвердит окно.'); setSel([]); setDlDate(''); } };
    const KINDS = [['all', 'Все'], ['risk', 'Требуют внимания'], ['decide', 'Ждут согласования'], ['client', 'Покупает клиент']];
    const pick = { all: () => true, risk: (r) => !!r.risk, decide: (r) => r.approval && r.approval !== 'approved', client: (r) => r.buyer === 'client' };
    const counts = {}; KINDS.forEach(([k]) => { counts[k] = s.rows.filter(pick[k]).length; });
    const groups = s.stages.map((g) => ({ ...g, rows: g.rows.filter(pick[tab]) })).filter((g) => g.rows.length);
    const threat = s.stages.filter((g) => g.threat);
    return (
      <Modal size="wide" className="lw-spec" title="Спецификация" onClose={close}
        sub={[s.total + ' ' + plural(s.total, 'позиция', 'позиции', 'позиций'), s.toDecide ? s.toDecide + ' ждут согласования' : '', s.late ? s.late + ' с просроченным сроком' : '', threat.length ? threat.length + ' ' + plural(threat.length, 'этап', 'этапа', 'этапов') + ' под угрозой' : ''].filter(Boolean).join(' · ')}>
        <div className="lw-spec-top">
          <CalTabs label="Какие позиции" kinds={KINDS} tab={tab} setTab={setTab} counts={counts} />
          {onSupply && <button type="button" className="lw-btn-l" onClick={onSupply}>Материалы и доставки</button>}
        </div>
        {sel.length > 0 && <div className="lw-spbar" role="region" aria-label="Доставка из выбранных позиций">
          <b>{sel.length} {plural(sel.length, 'позиция', 'позиции', 'позиций')}</b>
          <label><span className="lab">Привезти</span><input type="date" value={dlDate} onChange={(e) => setDlDate(e.target.value)} /></label>
          <button type="button" className="lw-btn-k" disabled={!dlDate} onClick={makeDl}>Создать доставку</button>
          <button type="button" className="lw-btn-l" onClick={() => setSel([])}>Снять выбор</button>
        </div>}
        {msg ? <div className="lab lw-spmsg">{msg}</div> : null}
        <div className="lab lw-spec-note">Сроки считаются от графика: привезти к старту этапа, заказать до — за срок поставки, решить до — к сроку заказа. Сдвинется этап — сдвинутся и сроки.</div>
        {groups.length ? groups.map((g) => (
          <section key={g.stageId || 'none'} className={'lw-spg' + (g.threat ? ' is-threat' : '')}>
            <div className="lw-spg-h">
              <span className="t">{g.name}{g.start ? <span className="lab">с {d(String(g.start).slice(0, 10))}</span> : null}</span>
              {g.threat ? <span className="lw-wst is-late">под угрозой · {g.reasons.map((x) => WHY_L[x]).join(', ')}</span> : g.warn ? <span className="lw-spst is-ask">скоро сроки</span> : null}
            </div>
            <div className="lw-spt" role="table" aria-label={'Позиции этапа ' + g.name}>
              <div className="lw-spr is-h" role="row"><span role="columnheader">Позиция</span><span role="columnheader">Покупает</span><span role="columnheader">Решить до</span><span role="columnheader">Заказать до</span><span role="columnheader">Привезти к</span><span role="columnheader">Статус</span></div>
              {g.rows.map((r) => { const [sl, sc] = status(r); return (
                <React.Fragment key={r.id}>
                <div className={'lw-spr' + (r.risk ? ' is-' + r.risk : '') + (sel.includes(r.id) ? ' is-sel' : '')} role="row">
                  <span className="tx" role="cell">
                    <span className="t">{canSel(r) ? <input type="checkbox" className="lw-spck" checked={sel.includes(r.id)} onChange={() => toggleSel(r.id)} aria-label={'Выбрать для доставки: ' + r.name} /> : null}{r.name}{r.version > 1 ? <span className="lw-spv">версия {r.version}</span> : null}</span>
                    <span className="lab">{[r.buyer === 'client' ? 'покупает клиент' : '', r.room, r.catL, qty(r.qty, r.unit), r.sum ? rub(r.sum) : ''].filter(Boolean).join(' · ')}</span>
                    {r.approval === 'rejected' && r.comment ? <span className="lab lw-spc">Клиент: «{r.comment}» — ждём новую версию от дизайнера</span> : null}
                    {r.deliveryCustom && r.deliveryDate ? <span className="lab">доставка {d(r.deliveryDate)}</span> : null}
                    {r.events.map((e) => <span key={e.id} className="lab lw-spe">{e.title} · {d(e.date)}{e.end && e.end !== e.date ? ' — ' + d(e.end) : ''}</span>)}
                    {onEvent && !r.onSite && ev !== r.id ? <button type="button" className="lw-splink" onClick={() => setEv(r.id)}>+ событие на график</button> : null}
                  </span>
                  <span role="cell" className="lab lw-spb" data-l="Покупает">{r.buyer === 'client' ? 'клиент' : 'мы'}</span>
                  <span role="cell" data-l="Решить до">{r.approval ? due(r, 'decide', r.decideBy) : <span className="lab">—</span>}</span>
                  <span role="cell" data-l="Заказать до">{due(r, 'order', r.orderBy)}</span>
                  <span role="cell" data-l="Привезти к">{due(r, 'deliver', r.needBy)}</span>
                  <span role="cell" data-l="Статус"><span className={sc}>{cap(sl)}</span></span>
                </div>
                {ev === r.id && <EvForm r={r} t0={t0} onSave={onEvent} onCancel={() => setEv(null)} />}
                </React.Fragment>); })}
            </div>
          </section>))
          : <div className="empty" style={{ marginTop: 14 }}>{tab === 'all' ? 'В смете объекта нет материалов.' : 'Таких позиций нет.'}</div>}
        {p && p.specGate ? <div className="lab lw-spec-note">Чистовую позицию, которая ждёт согласования, закупщик заказать не сможет — сначала решение клиента или дизайнера.</div> : null}
      </Modal>);
  }

  W.SpecW = SpecW;
})();
