/* lk-subs.jsx — «Подрядчики» для кабинетов сотрудников (прораб первым), в стиле окон кабинета клиента.
   Заказ подрядчику — пара «подрядчик + этап» из сметы (окна ОкнаЛюкс и т. п.): замер → счёт подрядчика → заказ с авансом → поставка →
   монтаж (работы принимают, как у своих мастеров) → акт, гарантия, оплата. SubsW — окно по объектам: слева что ждёт прораба (внести счёт,
   разместить заказ, принять поставку) и оплаты подрядчикам (платит бухгалтер), справа карточки заказов с шагами, сроками и суммами.
   Действия — функции ProjectStore, что и в старом кабинете (enterSubInvoice, orderSub, deliverSub, inviteSub, cancelSubOrder), через
   onInvoice / onOrder / onDeliver / onLink / onCancel кабинета; каждая возвращает {} или { error }. Данные — ForemanViews.subs().
   Exports on window: LKW.SubsW (дописывает в библиотеку lk-widgets.jsx, грузится после неё). */
(function () {
  'use strict';
  const W = window.LKW;
  const { Ic, Modal, CalTabs, rub, plural, dateR, short } = W;
  const dm = (d) => (d ? dateR(d, { month: 'short' }) : '');
  const orders = (n) => n + ' ' + plural(n, 'заказ', 'заказа', 'заказов');
  const tel = (s) => 'tel:' + String(s).replace(/[^+\d]/g, '');

  /* счёт подрядчика: сумма и файл; сразу видно, во что это выльется клиенту — совпало со сметой или уйдёт допсоглашение */
  function InvoiceForm({ o, onSave, onClose }) {
    const [sum, setSum] = React.useState(o.invoice ? String(o.invoice.cost) : '');
    const [file, setFile] = React.useState(null);
    const [busy, setBusy] = React.useState(false);
    const [err, setErr] = React.useState('');
    const cost = Math.round(+sum || 0);
    const client = Math.round(cost * (1 + o.margin / 100));
    const diff = client - o.estClient;
    const save = () => {
      setBusy(true); setErr('');
      Promise.resolve(onSave(cost, file)).then((r) => { setBusy(false); if (r && r.error) setErr(r.error); else onClose(); });
    };
    return (
      <div className="lw-sform">
        <div className="lw-sformf">
          <label className="lw-afld"><span className="lab">Сумма счёта подрядчика</span><span className="in"><input type="number" min={0} step={100} inputMode="numeric" value={sum} onChange={(e) => setSum(e.target.value)} aria-label="Сумма счёта подрядчика" /><span className="u">₽</span></span></label>
          <label className="lw-btn-l lw-hup">{file ? file.name : 'Файл счёта'}<input type="file" accept="application/pdf,image/*" hidden onChange={(e) => setFile((e.target.files || [])[0] || null)} /></label>
        </div>
        {cost > 0 && <div className={'lab' + (diff ? ' is-late' : ' is-ok')}>{'Клиенту по счёту ' + rub(client) + (diff ? ', на ' + rub(Math.abs(diff)) + (diff > 0 ? ' больше' : ' меньше') + ' сметы. Клиенту уйдёт допсоглашение, заказ — после его ответа' : '. Совпадает со сметой, можно размещать заказ')}</div>}
        {err && <div className="lab is-late" role="alert">{err}</div>}
        <div className="lw-sformb"><button type="button" className="lw-lnk lab" onClick={onClose}>Отмена</button>
          <button type="button" className="lw-btn-k" disabled={!(cost > 0) || busy} onClick={save}>{busy ? 'Сохраняем…' : 'Внести счёт'}</button></div>
      </div>);
  }

  /* поставка подрядчика на объект: сколько привезли, всё ли целое, заметка и фото */
  function DeliverForm({ o, onSave, onClose }) {
    const [qty, setQty] = React.useState(String(o.qty || ''));
    const [ok, setOk] = React.useState(true);
    const [note, setNote] = React.useState('');
    const [files, setFiles] = React.useState([]);
    const [busy, setBusy] = React.useState(false);
    const [err, setErr] = React.useState('');
    const save = () => {
      setBusy(true); setErr('');
      Promise.resolve(onSave({ qty: qty === '' ? null : +qty, ok, note: note.trim() }, files)).then((r) => { setBusy(false); if (r && r.error) setErr(r.error); else onClose(); });
    };
    return (
      <div className="lw-sform">
        <div className="lw-sformf">
          <label className="lw-afld"><span className="lab">Привезли{o.qty ? ', по заказу ' + o.qty + (o.unit ? ' ' + o.unit : '') : ''}</span><span className="in"><input type="number" min={0} inputMode="numeric" value={qty} onChange={(e) => setQty(e.target.value)} aria-label="Сколько привезли" /><span className="u">{o.unit}</span></span></label>
          <label className="lw-btn-l lw-hup">{files.length ? 'Фото · ' + files.length : 'Фото поставки'}<input type="file" accept="image/*" multiple hidden onChange={(e) => setFiles(Array.from(e.target.files || []))} /></label>
        </div>
        <label className="lw-scheck"><input type="checkbox" checked={ok} onChange={(e) => setOk(e.target.checked)} /> Всё целое, без повреждений</label>
        <input className="lw-sinp" placeholder={ok ? 'Заметка, если нужна' : 'Что не так и что заменить'} value={note} onChange={(e) => setNote(e.target.value)} aria-label="Заметка к поставке" />
        {err && <div className="lab is-late" role="alert">{err}</div>}
        <div className="lw-sformb"><button type="button" className="lw-lnk lab" onClick={onClose}>Отмена</button>
          <button type="button" className="lw-btn-k" disabled={busy || (!ok && !note.trim())} onClick={save}>{busy ? 'Сохраняем…' : 'Принять поставку'}</button></div>
      </div>);
  }

  /* отмена заказа: работы подрядчика уходят из графика, его цена — из договора клиента */
  function CancelForm({ o, onSave, onClose }) {
    const [why, setWhy] = React.useState('');
    const [err, setErr] = React.useState('');
    const save = () => { const r = onSave(why.trim()) || {}; if (r.error) setErr(r.error); else onClose(); };
    return (
      <div className="lw-sform">
        <div className="lab">Работы «{o.stage}» уйдут из графика, {rub(o.estClient)} — из договора клиента{o.prepay && o.prepay.status === 'paid' ? '. Аванс подрядчику уже выплачен, его нужно вернуть' : ''}.</div>
        <input className="lw-sinp" placeholder="Причина отмены" value={why} onChange={(e) => setWhy(e.target.value)} aria-label="Причина отмены заказа" />
        {err && <div className="lab is-late" role="alert">{err}</div>}
        <div className="lw-sformb"><button type="button" className="lw-lnk lab" onClick={onClose}>Не отменять</button>
          <button type="button" className="lw-btn-l" disabled={!why.trim()} onClick={save}>Отменить заказ</button></div>
      </div>);
  }

  /* карточка заказа: шаги, что ждём, сроки и деньги; действие прораба — одной кнопкой, форма раскрывается на месте */
  function OrderCard({ o, one, form, setForm, h }) {
    const [link, setLink] = React.useState(null);
    const closed = o.status === 'accepted' || o.status === 'paid';
    const mode = form && form.key === o.key ? form.k : null;
    const close = () => setForm(null);
    const doLink = () => { const r = h.onLink(o) || {}; setLink(r); };
    const meta = [
      ['Работы', o.worksN + ' ' + plural(o.worksN, 'работа', 'работы', 'работ') + (o.qty > 1 || o.unit ? ' · ' + o.qty + (o.unit ? ' ' + o.unit : '') : '') + (o.status === 'delivered' || closed ? ', принято ' + o.done : '')],
      ['По смете', rub(o.estClient)],
      ['По счёту', o.invoice ? rub(o.invoice.cost) + ', клиенту ' + rub(o.invoice.client) : ''],
      ['Замер', o.measureAt && o.status === 'measure' ? dm(o.measureAt) : ''],
      ['Поставка', o.delivery ? 'принята ' + dm(String(o.delivery.at).slice(0, 10)) + (o.delivery.ok ? '' : ', с замечаниями') : o.eta ? dm(o.eta) : ''],
      ['Монтаж', !closed && o.firstStart ? 'с ' + dm(o.firstStart) : ''],
      ['Аванс', o.prepay ? rub(o.prepay.amount) + (o.prepay.status === 'paid' ? ', оплачен' : ', к оплате у бухгалтера') : o.prepayPct && !closed ? o.prepayPct + ' % после заказа' : ''],
      ['Гарантия', o.warrantyUntil ? 'до ' + dateR(o.warrantyUntil, { month: 'short', year: 'numeric' }) : ''],
    ].filter((x) => x[1]);
    return (
      <div className={'cv-w cv-dlcard lw-dl lw-sord' + (o.next ? ' is-ask' : '') + (o.warns.some((w) => w.level === 'danger') ? ' is-late' : '')}>
        <div className="hd">
          <div style={{ minWidth: 0 }}>
            <div className="t">{o.subName} · {o.stage}</div>
            <div className="lab" style={{ marginTop: 3 }}>{[one ? '' : short(o.obj), o.contact].filter(Boolean).join(' · ')}{o.phone ? <React.Fragment>{' · '}<a className="lw-lnk" href={tel(o.phone)}>{o.phone}</a></React.Fragment> : null}</div>
          </div>
          <span className={o.rejected ? 'lw-wst is-late' : closed ? 'pill-g' : o.next ? 'pill-n' : 'pill-d'}>{o.statusL}</span>
        </div>
        <ol className="lw-sst" aria-label="Шаги заказа">{o.steps.map((x) => <li key={x.l} className={x.st ? 'is-' + x.st : ''}><i />{x.l}</li>)}</ol>
        {o.warns.map((w, i) => <div key={i} className={'lab lw-swarn' + (w.level === 'danger' ? ' is-late' : '')}><Ic n="alert" s={14} />{w.text}</div>)}
        {(o.next || o.wait) && <div className="lab lw-swait">{o.next ? o.next.why : o.wait}</div>}
        <dl className="cv-meta">{meta.map((x) => <div key={x[0]}><dt>{x[0]}</dt><dd>{x[1]}</dd></div>)}</dl>
        {mode === 'invoice' && <InvoiceForm o={o} onClose={close} onSave={(cost, file) => h.onInvoice(o, cost, file)} />}
        {mode === 'deliver' && <DeliverForm o={o} onClose={close} onSave={(rep, files) => h.onDeliver(o, rep, files)} />}
        {mode === 'cancel' && <CancelForm o={o} onClose={close} onSave={(why) => h.onCancel(o, why)} />}
        {mode === 'order-err' && <div className="lab is-late" role="alert">{form.err}</div>}
        {link && (link.error ? <div className="lab is-late" role="alert">{link.error}</div>
          : <div className="lab lw-wcopied">Ссылка скопирована, отправьте её подрядчику: он увидит только свой замер и свои работы. <a href={link.url} target="_blank" rel="noopener">Открыть</a></div>)}
        {(!mode || mode === 'order-err') && <div className="lw-dlact">
          <span className="lw-sacts">
            {o.taskId && <button type="button" className="cv-arrow-btn" onClick={() => h.onWork(o)}>Работы<Ic n="ne" s={13} /></button>}
            {o.mine && !closed && <button type="button" className="cv-arrow-btn" onClick={doLink}>Ссылка подрядчику<Ic n="ne" s={13} /></button>}
            {o.mine && !closed && <button type="button" className="lw-lnk lab" onClick={() => setForm({ key: o.key, k: 'cancel' })}>Отменить</button>}
          </span>
          <span className="lw-sacts">
            {o.next && o.next.k === 'order' && <button type="button" className="lw-btn-l" onClick={() => setForm({ key: o.key, k: 'invoice' })}>Изменить счёт</button>}
            {o.next && <button type="button" className="lw-btn-k" onClick={() => {
              if (o.next.k !== 'order') { setForm({ key: o.key, k: o.next.k }); return; }
              const r = h.onOrder(o) || {}; setForm(r.error ? { key: o.key, k: 'order-err', err: r.error } : null);
            }}>{o.next.l}</button>}
          </span>
        </div>}
      </div>);
  }

  function SubsW({ s, pid, onInvoice, onOrder, onDeliver, onLink, onCancel, onWork, onObject, close }) {
    const objs = s.objs.map((o) => ({ pid: o.pid, obj: o.obj }));
    const [tab, setTab] = React.useState(pid && objs.some((o) => o.pid === pid) ? pid : 'all');
    const [form, setForm] = React.useState(null);
    const inTab = (x) => tab === 'all' || x.pid === tab;
    const one = tab !== 'all' || objs.length === 1;
    const act = s.act.filter(inTab), pay = s.pay.filter(inTab), os = s.objs.filter(inTab);
    const all = os.flatMap((o) => o.orders);
    const counts = { all: s.counts.orders }; s.objs.forEach((o) => { counts[o.pid] = o.orders.length; });
    const h = { onInvoice, onOrder, onDeliver, onLink, onCancel, onWork };
    const warnN = all.filter((o) => o.warns.length).length;
    return (
      <Modal size="wide" className="lw-sup lw-subs" title="Подрядчики" onClose={close}
        sub={all.length ? [orders(all.length), act.length ? act.length + ' ждут вас' : 'от вас сейчас ничего не нужно', warnN ? warnN + ' под риском по срокам' : ''].filter(Boolean).join(' · ') : 'Заказов подрядчикам нет'}>
        {objs.length > 1 ? <CalTabs label="Объекты" kinds={[['all', 'Все объекты']].concat(objs.map((o) => [o.pid, short(o.obj)]))} tab={tab} setTab={setTab} counts={counts} /> : null}
        {!objs.length ? <div className="cv-w cv-dlcard is-quiet"><div className="lab">Заказы подрядчикам появляются, когда в смете объекта есть этап подрядчика, например замена окон. Замер, счёт, поставка и оплаты по нему будут здесь.</div></div>
          : <div className="cv-dlgrid lw-supg">
            <aside className="cv-dlside">
              <div className="cv-sec-h"><h2 className="h2">Ждут вас</h2>{act.length > 0 && <span className="lab">{act.length}</span>}</div>
              {act.length ? <div className="cv-w lw-plain lw-plist">{act.map((o) => (
                <div key={o.key} className="lw-hrow lw-prow">
                  <span className="tx"><span className="t">{o.next ? o.next.l + ' · ' + o.subName : o.subName}</span>
                    <span className="lab">{[one ? '' : short(o.obj), o.stage, o.next ? o.next.why : ''].filter(Boolean).join(' · ')}</span>
                    {o.warns.map((w, i) => <span key={i} className={'lab' + (w.level === 'danger' ? ' is-late' : ' lw-swarn')}>{w.text}</span>)}</span>
                  {o.next ? <button type="button" className="lw-btn-l" onClick={() => { setTab(tab === 'all' && !one ? o.pid : tab); setForm(o.next.k === 'order' ? null : { key: o.key, k: o.next.k }); }}>{o.next.k === 'order' ? 'Открыть' : o.next.l}</button>
                    : <button type="button" className="cv-arrow-btn" onClick={() => setTab(o.pid)}>Открыть<Ic n="ne" s={13} /></button>}
                </div>))}</div>
                : <div className="cv-w cv-dlcard is-quiet"><div className="lab">Сейчас от вас ничего не нужно: заказы ждут подрядчика или ответа клиента.</div></div>}
              <div className="lab lw-note">Вы вносите счёт после замера, размещаете заказ и принимаете поставку. Если счёт отличается от сметы, клиенту уйдёт допсоглашение.</div>

              <div className="cv-sec-h lw-sup-h"><h2 className="h2">Оплаты подрядчикам</h2></div>
              {pay.length ? <div className="cv-w lw-plain lw-mlist">{pay.map((x) => (
                <div key={x.key} className="lw-mrow">
                  <span className="tx"><span className="t">{x.subName + ' · ' + x.part + ' ' + rub(x.amount)}</span><span className="lab">{[one ? '' : short(x.obj), x.stage].filter(Boolean).join(' · ')}</span></span>
                  <span className={'lab' + (x.paid ? '' : ' is-ask')}>{x.paid ? 'оплачен ' + dm(x.paidAt) : 'к оплате'}</span>
                </div>))}</div>
                : <div className="cv-w cv-dlcard is-quiet"><div className="lab">Аванс появится после размещения заказа, остаток — после приёмки работ.</div></div>}
              <div className="lab lw-note">Аванс и остаток подрядчику платит бухгалтер, отмечать оплату не нужно.</div>
            </aside>
            <div className="lw-supm">
              <div className="cv-sec-h"><h2 className="h2">Заказы</h2><span className="lab">{orders(all.length)}</span></div>
              {os.map((ob) => (
                <div key={ob.pid} className="lw-pobj">
                  {!one && <div className="lw-mobj-h"><button type="button" className="cv-arrow-btn" onClick={() => onObject(ob.pid)}>{short(ob.obj)}<Ic n="ne" s={14} /></button><span className="lab">{orders(ob.orders.length)}</span></div>}
                  <div className="cv-dlist one">{ob.orders.map((o) => <OrderCard key={o.key} o={o} one={one} form={form} setForm={setForm} h={h} />)}</div>
                </div>))}
            </div>
          </div>}
      </Modal>);
  }

  W.SubsW = SubsW;
})();
