// ov2-heatmap14.jsx — self-contained occupancy heatmap block

const HM14_e = React.createElement;

const HM14_fmt = (tpl, vars = {}) => String(tpl || '').replace(/\{(\w+)\}/g, (_, key) => (
  vars[key] === 0 || vars[key] ? vars[key] : ''
));
const HM14_money = (value) => `€${Math.round(value || 0).toLocaleString('en-US')}`;
const HM14_rangeLabel = (fromDay, toDay, lang) => {
  const months = window.HM14.MONTHS[lang] || window.HM14.MONTHS.ru;
  const from = `${fromDay.day} ${months[fromDay.month]}`;
  const to = `${toDay.day} ${months[toDay.month]}`;
  return `${from} — ${to}`;
};
const HM14_shortDate = (day, lang) => {
  const months = window.HM14.MONTHS[lang] || window.HM14.MONTHS.ru;
  return `${day.day} ${months[day.month]}`;
};

const HM14_PaymentDot = ({ status, t }) => (
  <span className={`hm14-pay-dot ${status || 'hold'}`} title={(t.payment || {})[status] || status}></span>
);

const HM14_TaskList = ({ tasks, t, doneMap, onToggle }) => (
  <div className="hm14-task-list">
    {tasks.length ? tasks.map((task) => {
      const checked = Object.prototype.hasOwnProperty.call(doneMap, task.id) ? doneMap[task.id] : !!task.done;
      return (
        <label className={`hm14-task ${task.prio || 'low'} ${checked ? 'done' : ''}`} key={task.id}>
          <input type="checkbox" checked={checked} onChange={() => onToggle(task.id, !checked)} />
          <span>{task.text}</span>
          <em>{task.source === 'booking' ? t.drawer.booking : 'ops'}</em>
        </label>
      );
    }) : <div className="hm14-empty-tasks">{t.drawer.noTasks}</div>}
  </div>
);

const HM14_Tooltip = ({ tooltip, lang, t }) => {
  if (!tooltip) return null;
  const { model, cabin, day, tasks, x, y } = tooltip;
  const res = model.res;
  const title = `${cabin.name} · ${window.HM14.fmtFullDate(day.idx, lang)}`;
  return (
    <div className="hm14-tooltip" style={{ left: x, top: y }}>
      <div className="hm14-tooltip-title">{title}</div>
      <div className="hm14-tooltip-sep"></div>
      {model.type === 'free' ? (
        <>
          <div>{t.type.free}</div>
          <div className="hm14-tooltip-muted">{t.drawer.freeHint}</div>
        </>
      ) : model.type === 'blocked' ? (
        <>
          <div>{t.type.blocked}: {res.reason}</div>
          <div className="hm14-tooltip-muted">{res.note}</div>
        </>
      ) : (
        <>
          <div>{res.flag} {res.guest}</div>
          <div className="hm14-tooltip-muted">{res.channel} · {HM14_money(res.total)} · {res.seg}</div>
          <div className={`hm14-tooltip-pay ${res.pay}`}>{t.drawer.payment}: {t.payment[res.pay]}</div>
          <div className="hm14-tooltip-flags">
            {model.isArrival && <span>{t.marker.arrival}</span>}
            {model.isDeparture && <span>{t.marker.departure}</span>}
            {res.repeat > 1 && <span>×{res.repeat}</span>}
          </div>
        </>
      )}
      {tasks.slice(0, 3).map((task) => <div className={`hm14-tooltip-task ${task.prio}`} key={task.id}>{task.text}</div>)}
    </div>
  );
};

const HM14_DayCell = ({ cabin, day, model, tasks, t, onOpen, onHover, onLeave }) => {
  const res = model.res;
  const highTasks = tasks.filter((task) => task.prio === 'high' && !task.done).length;
  const cls = [
    'hm14-cell',
    model.type,
    day.isToday ? 'today' : '',
    day.isWeekend ? 'weekend' : '',
    res && res.overdue ? 'overdue' : '',
  ].filter(Boolean).join(' ');

  return (
    <button
      type="button"
      className={cls}
      onClick={() => onOpen({ cabin, day, model, tasks })}
      onMouseEnter={(e) => onHover(e, { cabin, day, model, tasks })}
      onMouseMove={(e) => onHover(e, { cabin, day, model, tasks })}
      onMouseLeave={onLeave}
    >
      {model.type === 'free' ? (
        <span className="hm14-free-label"></span>
      ) : model.type === 'blocked' ? (
        <span className="hm14-blocked-label">БЛОК</span>
      ) : (
        <>
          <div className="hm14-cell-top">
            <span className="hm14-guest">{res.flag} <strong>{res.init}</strong>{res.repeat > 1 && <em>×{res.repeat}</em>}</span>
            <span className="hm14-markers">
              {model.isArrival && <span className="hm14-arr">▲</span>}
              {model.isDeparture && <span className="hm14-dep">▼</span>}
              {highTasks > 0 && <span className="hm14-task-badge">!{highTasks}</span>}
              <HM14_PaymentDot status={res.pay} t={t} />
            </span>
          </div>
          <div className="hm14-cell-meta">{HM14_money(res.price)} · {res.channel} · {res.seg}</div>
          <div className="hm14-pills">
            {res.spa && <span>SPA</span>}
            {res.fnb && <span>F&B</span>}
            {tasks[0] && <span className={`task ${tasks[0].prio}`}>☐ {tasks[0].text}</span>}
          </div>
        </>
      )}
    </button>
  );
};

const HM14_DrawerRow = ({ label, value }) => (
  <div className="hm14-drawer-row">
    <span>{label}</span>
    <strong>{value || '-'}</strong>
  </div>
);

const HM14_Drawer = ({ data, lang, t, doneMap, onToggle, onClose }) => {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  if (!data) return null;
  const { cabin, day, model, tasks } = data;
  const res = model.res;
  const isBooking = res && !res.blocked && model.type !== 'free';
  const title = isBooking ? `${t.drawer.booking} ${res.id} · ${cabin.name}` : model.type === 'blocked' ? `${t.drawer.blocked} · ${cabin.name}` : `${t.drawer.free} · ${cabin.name}`;
  const statusLabel = t.type[model.type] || model.type;
  const operation = model.type === 'free'
    ? t.drawer.freeHint
    : model.type === 'blocked'
      ? t.drawer.blockedHint
      : model.isArrival
        ? t.drawer.opArrival
        : model.isDeparture
          ? t.drawer.opDeparture
          : model.type === 'inhouse'
            ? t.drawer.opInhouse
            : model.type === 'checkedout'
              ? t.drawer.opPast
              : t.drawer.opFuture;

  return (
    <>
      <div className="hm14-overlay" onClick={onClose}></div>
      <aside className="hm14-drawer">
        <div className="hm14-drawer-head">
          <div>
            <div className="hm14-drawer-title">{title}</div>
            <div className="hm14-drawer-sub">{window.HM14.fmtFullDate(day.idx, lang)} · {statusLabel}</div>
          </div>
          <button type="button" onClick={onClose} aria-label="Close">×</button>
        </div>
        <div className="hm14-drawer-body">
          {isBooking && (
            <div className="hm14-summary">
              <div><span>{t.drawer.price}</span><strong>{HM14_money(res.price)}</strong></div>
              <div><span>{t.drawer.total}</span><strong>{HM14_money(res.total)}</strong></div>
              <div className={`pay ${res.pay}`}><span>{t.drawer.payment}</span><strong>{t.payment[res.pay]}</strong></div>
            </div>
          )}
          <section className="hm14-drawer-section">
            <h4>{t.drawer.operations}</h4>
            <div className="hm14-op-note">{operation}</div>
          </section>
          <section className="hm14-drawer-section">
            <h4>{t.drawer.tasks}</h4>
            <HM14_TaskList tasks={tasks} t={t} doneMap={doneMap} onToggle={onToggle} />
          </section>
          {isBooking ? (
            <>
              <section className="hm14-drawer-section">
                <h4>{t.drawer.client}</h4>
                <HM14_DrawerRow label={t.labels.guest} value={res.guest} />
                <HM14_DrawerRow label={t.labels.country} value={`${res.flag} ${res.country}`} />
                <HM14_DrawerRow label={t.labels.segment} value={res.seg} />
                <HM14_DrawerRow label={t.labels.repeat} value={res.repeat > 1 ? `×${res.repeat}` : 'new'} />
                <HM14_DrawerRow label={t.labels.contacts} value={`${res.email} · ${res.phone}`} />
              </section>
              <section className="hm14-drawer-section">
                <h4>{t.drawer.source}</h4>
                <HM14_DrawerRow label={t.labels.channel} value={res.channel} />
                <HM14_DrawerRow label={t.labels.discovery} value={res.discovery} />
              </section>
              <section className="hm14-drawer-section">
                <h4>{t.drawer.bookingSec}</h4>
                <HM14_DrawerRow label={t.labels.id} value={res.id} />
                <HM14_DrawerRow label={t.labels.checkin} value="15:00" />
                <HM14_DrawerRow label={t.labels.checkout} value="12:00" />
              </section>
              {res.note && (
                <section className="hm14-note">
                  <h4>{t.drawer.note}</h4>
                  <div>{res.note}</div>
                </section>
              )}
            </>
          ) : (
            <section className="hm14-drawer-section">
              <h4>{model.type === 'blocked' ? t.labels.reason : t.drawer.free}</h4>
              <HM14_DrawerRow label={model.type === 'blocked' ? t.labels.reason : 'ADR'} value={model.type === 'blocked' ? res.reason : '€260'} />
            </section>
          )}
        </div>
        <div className="hm14-drawer-actions">
          <button type="button">{t.drawer.openCloudbeds}</button>
          <button type="button">{t.drawer.whatsapp}</button>
          {isBooking && (res.overdue || res.pay === 'unpaid' || res.pay === 'partial') && <button type="button" className="danger">{t.drawer.requestPayment}</button>}
        </div>
      </aside>
    </>
  );
};

const Heatmap14 = ({ lang = 'ru' }) => {
  const hm = window.HM14;
  const t = (window.HM14_I18N && (window.HM14_I18N[lang] || window.HM14_I18N.ru)) || {};
  const [windowOffset, setWindowOffset] = React.useState(hm.TODAY_IDX);
  const [daysCount, setDaysCount] = React.useState(7);
  const [drawerData, setDrawerData] = React.useState(null);
  const [tooltip, setTooltip] = React.useState(null);
  const [doneMap, setDoneMap] = React.useState({});
  const tooltipTimer = React.useRef(null);
  const days = hm.buildDays(windowOffset, daysCount);

  React.useEffect(() => () => window.clearTimeout(tooltipTimer.current), []);

  const cells = hm.CABINS.flatMap((cabin) => days.map((day) => {
    const model = hm.dayCellModel(cabin.id, day.idx);
    const tasks = hm.tasksFor(cabin.id, day.idx, model.res);
    return { cabin, day, model, tasks };
  }));
  const occupied = cells.filter((cell) => !['free', 'blocked'].includes(cell.model.type)).length;
  const blocked = cells.filter((cell) => cell.model.type === 'blocked').length;
  const free = cells.length - occupied - blocked;
  const overdue = cells.filter((cell) => cell.model.res && cell.model.res.overdue).length;
  const activeTasks = cells.reduce((sum, cell) => sum + cell.tasks.filter((task) => {
    const checked = Object.prototype.hasOwnProperty.call(doneMap, task.id) ? doneMap[task.id] : !!task.done;
    return !checked;
  }).length, 0);

  const showTooltip = (event, payload) => {
    window.clearTimeout(tooltipTimer.current);
    const rect = event.currentTarget.getBoundingClientRect();
    tooltipTimer.current = window.setTimeout(() => {
      setTooltip({
        ...payload,
        x: rect.left + rect.width / 2,
        y: rect.top - 10,
      });
    }, 80);
  };
  const hideTooltip = () => {
    window.clearTimeout(tooltipTimer.current);
    setTooltip(null);
  };
  const toggleTask = (id, done) => setDoneMap((state) => ({ ...state, [id]: done }));

  return (
    <div className="card hm14-card" data-screen-label="06 Heatmap14">
      <div className="hm14-top">
        <div className="hm14-title-wrap">
          <div className="card-title">{HM14_fmt(t.title, { n: daysCount })}</div>
          <span className="hm14-help" title={t.help}>?</span>
          <div className="hm14-range">{HM14_fmt(t.range, { from: HM14_shortDate(days[0], lang), to: HM14_shortDate(days[days.length - 1], lang) })}</div>
        </div>
        <div className="hm14-controls">
          <button type="button" onClick={() => setWindowOffset((v) => v - daysCount)} aria-label={t.prev}>‹</button>
          <button type="button" onClick={() => setWindowOffset(hm.TODAY_IDX)}>{t.today}</button>
          <button type="button" onClick={() => setWindowOffset((v) => v + daysCount)} aria-label={t.next}>›</button>
          <div className="hm14-toggle">
            {[7, 14, 30].map((n) => (
              <button type="button" className={daysCount === n ? 'active' : ''} onClick={() => setDaysCount(n)} key={n}>{t.toggles[n]}</button>
            ))}
          </div>
        </div>
      </div>

      <div className="hm14-stats">
        <span><strong>{occupied}</strong> {t.stats.occupied}</span>
        <span><strong>{free}</strong> {t.stats.free}</span>
        <span className={overdue ? 'danger' : ''}><strong>{overdue}</strong> {t.stats.overdue}</span>
        <span><strong>{activeTasks}</strong> {t.stats.tasks}</span>
      </div>

      <div className="hm14-legend">
        <span><i className="inhouse"></i>{t.legend.inhouse}</span>
        <span><i className="booked"></i>{t.legend.booked}</span>
        <span><i className="free"></i>{t.legend.free}</span>
        <span><i className="arrdep">▲</i>{t.legend.arrdep}</span>
        <span><i className="pay"></i>{t.legend.pay}</span>
        <span><i className="overdue"></i>{t.legend.overdue}</span>
      </div>

      <div className="hm14-scroll">
        <div className="hm14-grid" style={{ gridTemplateColumns: `148px repeat(${daysCount}, minmax(112px, 1fr))` }}>
          <div className="hm14-corner"></div>
          {days.map((day) => {
            const dow = hm.DOW[lang] || hm.DOW.ru;
            const months = hm.MONTHS[lang] || hm.MONTHS.ru;
            return (
              <div className={`hm14-day-head ${day.isToday ? 'today' : ''} ${day.isWeekend ? 'weekend' : ''}`} key={day.idx}>
                <span>{dow[day.dow]}</span>
                <strong>{day.day} {day.day === 1 || day.idx === windowOffset ? months[day.month] : ''}</strong>
              </div>
            );
          })}
          {hm.CABINS.map((cabin) => (
            <React.Fragment key={cabin.id}>
              <div className="hm14-cabin">
                <strong>{cabin.name}</strong>
                <span>{cabin.sub}</span>
              </div>
              {days.map((day) => {
                const model = hm.dayCellModel(cabin.id, day.idx);
                const tasks = hm.tasksFor(cabin.id, day.idx, model.res);
                return (
                  <HM14_DayCell
                    key={`${cabin.id}-${day.idx}`}
                    cabin={cabin}
                    day={day}
                    model={model}
                    tasks={tasks}
                    t={t}
                    onOpen={setDrawerData}
                    onHover={showTooltip}
                    onLeave={hideTooltip}
                  />
                );
              })}
            </React.Fragment>
          ))}
        </div>
      </div>

      <HM14_Tooltip tooltip={tooltip} lang={lang} t={t} />
      <HM14_Drawer data={drawerData} lang={lang} t={t} doneMap={doneMap} onToggle={toggleTask} onClose={() => setDrawerData(null)} />
    </div>
  );
};

window.Heatmap14 = Heatmap14;
