/* room-readiness-view.jsx — готовность по комнатам в окне «Реализация» кабинета клиента v2 (KSH-504, часть 2).
   Шапка: «Готовность ремонта N %» с подписью «по работам, принятым прорабом» (ProjectStore.roomReadiness(p).repair — без фазы 0 «Дизайн и
   согласования», замеров и вех; деньги-взвешенное среднее плиток, решение владельца 03.11) и рядом — статус фазы 0 отдельной плашкой
   по названию фазы («Дизайн и согласования ✓ приняты» / «Дизайн и согласования: в работе · N из M»; у проекта без задач фазы 0 плашки нет);
   ряд плиток — кольцо, процент, комната, «сейчас: <этап>»;
   плитка — кнопка-фильтр списка этапов (состояние фильтра — в окне, это только вид). Проект без комнат (roomReadiness → null) — ничего не рисуем.
   Клиенту: ни денег, ни внутренних шагов пакетов — только проценты и названия этапов. Печать — плитки простым списком.
   Зависит от React и ProjectStore (читается в момент вызова). Exports on window: RoomReadiness { model, match, designLabel, Overall, Tiles } */
(function () {
  'use strict';
  const OBJECT = 'object';
  const RING_R = 18, RING_C = 2 * Math.PI * RING_R;

  const objectId = () => (window.ProjectStore && window.ProjectStore.ROOM_OBJECT) || OBJECT;
  const stepsOf = (t, roomId) => Object.values((t.roomSteps && t.roomSteps[roomId]) || {});
  const hasRoom = (t, roomId) => !!(t.rooms && t.roomSteps && (t.rooms || []).some((r) => r.roomId === roomId) && stepsOf(t, roomId).length);
  const stageName = (p, t) => { const s = (p.stages || []).find((x) => x.id === t.stageId); return s ? (s.virtual ? 'Дополнительные работы' : s.name) : ''; };

  /* «сейчас» — этап самой ранней по порядку работы, где в комнате приняты не все шаги; все приняты — «готово» */
  function current(p, roomId, pct) {
    if (pct >= 100) return 'готово';
    const t = (p.tasks || []).filter((x) => hasRoom(x, roomId) && !stepsOf(x, roomId).every((s) => s && s.state === 'accepted'))
      .sort((a, b) => (a.order || 0) - (b.order || 0))[0];
    return t ? stageName(p, t) : '';
  }

  /* model(project) → { repair, design: { done, total } | null, tiles: [{ id, name, pct, now }] } | null (проект без комнат или без работ
     ремонта по комнатам); repair и плитки — по работам ремонта (rr.rooms), design — статус дизайн-проекта (rr.design) */
  function model(project) {
    const P = window.ProjectStore;
    const rr = P && project && P.roomReadiness ? P.roomReadiness(project) : null;
    if (!rr) return null;
    const obj = objectId();
    const floorOf = (r) => (r.floor == null ? 1 : +r.floor || 0);
    const tiles = (project.rooms || []).map((r, i) => ({ r, i })).filter(({ r }) => rr.rooms[r.id] != null)
      .sort((a, b) => (!!a.r.outdoor - !!b.r.outdoor) || (floorOf(a.r) - floorOf(b.r)) || (a.i - b.i))
      .map(({ r }) => ({ id: r.id, name: r.name || '', pct: rr.rooms[r.id], now: current(project, r.id, rr.rooms[r.id]) }));
    if (rr.rooms[obj] != null) tiles.push({ id: obj, name: 'Объект целиком', pct: rr.rooms[obj], now: current(project, obj, rr.rooms[obj]) });
    if (!tiles.length) return null;
    return { repair: rr.repair, design: rr.design || null, tiles };
  }

  /* match(project, roomId) → { [номер этапа]: Set(индекс работы в этапе) }: какие работы окна «Реализация» (V.clientStages: этап n = n-й
     не виртуальный этап, работа j = j-я не веха этапа) имеют часть в комнате */
  function match(project, roomId) {
    const out = {};
    (project.stages || []).filter((s) => !s.virtual).forEach((s, i) => {
      (project.tasks || []).filter((t) => t.stageId === s.id && t.kind !== 'milestone').forEach((t, j) => {
        if (hasRoom(t, roomId)) (out[i + 1] = out[i + 1] || new Set()).add(j);
      });
    });
    return out;
  }

  function Ring({ pct }) {
    return (
      <svg className="cv-rr-ring" viewBox="0 0 44 44" width="44" height="44" aria-hidden="true">
        <circle className="bg" cx="22" cy="22" r={RING_R} fill="none" strokeWidth="4" />
        <circle className="fg" cx="22" cy="22" r={RING_R} fill="none" strokeWidth="4" strokeLinecap="round" transform="rotate(-90 22 22)"
          strokeDasharray={RING_C.toFixed(2)} strokeDashoffset={(RING_C * (1 - Math.min(100, Math.max(0, pct)) / 100)).toFixed(2)} />
      </svg>);
  }

  /* статус фазы 0 по её названию (rr.design.name, нет — «Дизайн и согласования»): все задачи приняты — «✓ приняты», иначе —
     «в работе · N из M»; задач фазы 0 нет — null */
  function designLabel(d) {
    if (!d || !d.total) return null;
    const name = d.name || 'Дизайн и согласования';
    return d.done >= d.total ? name + ' ✓ приняты' : name + ': в работе · ' + d.done + ' из ' + d.total;
  }

  /* «Готовность ремонта N %» и плашка фазы 0 — справа от заголовка окна; денег нет */
  function Overall({ model: m }) {
    if (!m) return null;
    const dl = designLabel(m.design);
    return (
      <React.Fragment>
        <div className="cv-rr-all" aria-label={'Готовность ремонта ' + m.repair + ' %, по работам, принятым прорабом'}>
          <span className="k">Готовность ремонта</span><b className="num">{m.repair}%</b><span className="cap">по работам, принятым прорабом</span>
        </div>
        {dl && <span className={'cv-rr-dp' + (m.design.done >= m.design.total ? ' is-done' : '')}>{dl}</span>}
      </React.Fragment>);
  }

  /* ряд плиток и строка активного фильтра; sel — id выбранной комнаты, onSelect(id | null) */
  function Tiles({ model: m, sel, onSelect }) {
    if (!m) return null;
    const cur = sel ? m.tiles.find((t) => t.id === sel) : null;
    return (
      <section className="cv-rr" aria-label="Готовность по комнатам">
        <div className="cv-rr-row">
          {m.tiles.map((t) => (
            <button key={t.id} type="button" className={'cv-rr-tile' + (sel === t.id ? ' on' : '') + (t.pct >= 100 ? ' is-done' : '')} aria-pressed={sel === t.id ? "true" : "false"}
              aria-label={t.name + ', готово ' + t.pct + ' %'} onClick={() => onSelect(sel === t.id ? null : t.id)}>
              <Ring pct={t.pct} />
              <span className="tx"><span className="p num">{t.pct}%</span><span className="nm">{t.name}</span>{t.now && <span className="now">{t.now === 'готово' ? 'готово' : 'сейчас: ' + t.now}</span>}</span>
            </button>))}
        </div>
        {cur && <div className="cv-rr-flt"><span>{cur.name} · {cur.pct}%</span><button type="button" className="cv-rr-all-btn" onClick={() => onSelect(null)}>Показать все</button></div>}
      </section>);
  }

  window.RoomReadiness = { model, match, designLabel, Overall, Tiles };
})();
