/* ProjectDetail.jsx — Registros sheet for ONE project, scoped to the current
   month. Columns = this month's logged days, padded with empty slots. All
   counts persist all-time in project.counts (read by Totales / C-69). */
const { useState: useS, useRef: useR, useEffect: useE } = React;

const kOf = (iso, rowId) => `${iso}|${rowId}`;

function StepGroup({ t, L, style, value, onChange }) {
  return (
    <div>
      <div style={{ display: 'flex', gap: 3 }}>
        {window.APP.STEPS.map((s, i) => {
          const sel = s === value;
          const r1 = i === 0 ? 100 : 9, r2 = i === window.APP.STEPS.length - 1 ? 100 : 9;
          return (
            <button key={s} onClick={() => onChange(s)} style={{
              flex: 1, height: 42, minWidth: 0, cursor: 'pointer', border: 'none',
              borderRadius: `${r1}px ${r2}px ${r2}px ${r1}px`,
              background: sel ? t.primary : (style.stepFilled ? t.surfContHigh : 'transparent'),
              outline: !sel && !style.stepFilled ? `1px solid ${t.outlineVariant}` : 'none', outlineOffset: -1,
              color: sel ? t.onPrimary : (s === 0 ? t.onSurfaceVariant : t.onSurface),
              fontSize: 15.5, fontWeight: 700, transition: 'background .14s, transform .1s', transform: sel ? 'scale(1.04)' : 'none',
            }}>{s > 0 ? `+${s}` : `${s}`}</button>
          );
        })}
      </div>
    </div>
  );
}

function Cell({ t, style, dens, value, maxv, onApply, step, disabled }) {
  const [pulse, setPulse] = useS(0);
  const [floatTxt, setFloatTxt] = useS(null);
  const timer = useR(null), longRef = useR(false);
  const fire = (delta) => {
    if (disabled) return;
    if (delta === 0) { if (value > 0) onApply(-value); setPulse((p) => p + 1); setFloatTxt({ id: Date.now(), txt: '0' }); return; }
    onApply(delta); setPulse((p) => p + 1); setFloatTxt({ id: Date.now(), txt: (delta > 0 ? '+' : '') + delta });
  };
  useE(() => { if (!floatTxt) return; const id = setTimeout(() => setFloatTxt(null), 650); return () => clearTimeout(id); }, [floatTxt]);
  const down = () => { if (disabled) return; longRef.current = false; timer.current = setTimeout(() => { longRef.current = true; fire(-step); }, 420); };
  const up = () => { clearTimeout(timer.current); if (!longRef.current) fire(step); };
  const leave = () => clearTimeout(timer.current);
  const ctx = (e) => { e.preventDefault(); fire(-step); };

  let bg = 'transparent';
  if (!disabled && style.cellTint && value > 0) { const op = Math.min(0.18 + (value / (maxv || 1)) * 0.82, 1); bg = `color-mix(in srgb, ${t.primaryContainer} ${Math.round(op * 100)}%, transparent)`; }
  return (
    <div onMouseDown={down} onMouseUp={up} onMouseLeave={leave} onContextMenu={disabled ? undefined : ctx}
      style={{ height: dens.cellH, width: dens.cellW, position: 'relative', cursor: disabled ? 'default' : 'pointer',
        display: 'flex', alignItems: 'center', justifyContent: 'center', userSelect: 'none',
        borderRight: style.gridLines ? `1px solid ${t.outlineVariant}` : 'none', borderBottom: style.gridLines ? `1px solid ${t.outlineVariant}` : 'none',
        background: disabled ? `repeating-linear-gradient(135deg, transparent, transparent 5px, ${t.outlineVariant}22 5px, ${t.outlineVariant}22 6px)` : bg,
        WebkitTapHighlightColor: 'transparent', boxSizing: 'border-box' }}>
      {!disabled && <span key={pulse} style={{ fontSize: dens.cellFont, fontWeight: value ? 700 : 400, color: value ? t.onSurface : t.onSurfaceVariant + '66', animation: pulse ? 'cellPop .32s cubic-bezier(.2,.9,.2,1.2)' : 'none' }}>{value || 0}</span>}
      {floatTxt && <span key={floatTxt.id} style={{ position: 'absolute', top: 2, fontSize: 13, fontWeight: 800, color: floatTxt.txt === '0' ? t.onSurfaceVariant : (floatTxt.txt[0] === '+' ? t.primary : t.error), animation: 'floatUp .65s ease-out forwards', pointerEvents: 'none' }}>{floatTxt.txt}</span>}
    </div>
  );
}

function RowLabel({ t, dens, name, onRename }) {
  const [edit, setEdit] = useS(false);
  const [v, setV] = useS(name);
  useE(() => setV(name), [name]);
  const commit = () => { setEdit(false); onRename(v.trim() || name); };
  return (
    <div onClick={() => !edit && setEdit(true)} style={{ height: dens.cellH, width: dens.rowLabelW, display: 'flex', alignItems: 'center', padding: '0 8px 0 14px', boxSizing: 'border-box', cursor: 'text' }}>
      {edit ? (
        <input autoFocus value={v} onChange={(e) => setV(e.target.value)} onBlur={commit}
          onKeyDown={(e) => { if (e.key === 'Enter') commit(); if (e.key === 'Escape') { setV(name); setEdit(false); } }}
          style={{ width: '100%', border: 'none', borderBottom: `2px solid ${t.primary}`, background: 'transparent', color: t.onSurface, fontSize: 15, fontWeight: 600, outline: 'none', fontFamily: 'inherit', padding: '2px 0' }} />
      ) : (
        <span style={{ fontSize: 15, fontWeight: 600, color: t.onSurface, lineHeight: 1.15, overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical' }}>{name}</span>
      )}
    </div>
  );
}

function HSlider({ t, scrollRef, deps }) {
  const [m, setM] = useS({ max: 0, val: 0, cw: 0, sw: 0 });
  const measure = () => { const el = scrollRef.current; if (!el) return; setM({ max: Math.max(0, el.scrollWidth - el.clientWidth), val: el.scrollLeft, cw: el.clientWidth, sw: el.scrollWidth }); };
  useE(() => { const id = setTimeout(measure, 40); return () => clearTimeout(id); }, deps);
  useE(() => { const el = scrollRef.current; if (!el) return; const h = () => setM((p) => ({ ...p, val: el.scrollLeft, max: Math.max(0, el.scrollWidth - el.clientWidth) })); el.addEventListener('scroll', h, { passive: true }); return () => el.removeEventListener('scroll', h); }, []);
  if (m.max < 2) return null;
  return (
    <div style={{ flexShrink: 0, padding: '6px 16px 10px', background: t.surface, display: 'flex', alignItems: 'center', gap: 10 }}>
      <Icon name="counter" size={16} color={t.onSurfaceVariant + '88'} />
      <input className="hslider" type="range" min={0} max={Math.round(m.max)} value={Math.round(m.val)}
        onChange={(e) => { if (scrollRef.current) scrollRef.current.scrollLeft = +e.target.value; }}
        style={{ flex: 1, color: t.primary, '--track': t.outlineVariant + '55' }} />
    </div>
  );
}

function ColDateDialog({ t, L, iso, onClose, onSave }) {
  const [v, setV] = useS(iso);
  return (
    <Dialog t={t} onClose={onClose}>
      <h2 style={{ margin: '0 0 10px', fontSize: 22, fontWeight: 600, color: t.onSurface }}>{L.changeDateT}</h2>
      <div style={{ fontSize: 14, color: t.onSurfaceVariant, lineHeight: 1.5, margin: '0 0 18px' }}>{L.changeDateMsg}</div>
      <label style={{ fontSize: 13, fontWeight: 600, color: t.onSurfaceVariant }}>{L.dateLabel}</label>
      <input type="date" value={v} onChange={(e) => setV(e.target.value)}
        style={{ width: '100%', marginTop: 8, boxSizing: 'border-box', border: `1px solid ${t.outline}`, borderRadius: 12, background: t.surfContLow, color: t.onSurface, fontSize: 17, fontWeight: 600, padding: '12px 14px', fontFamily: 'inherit', outline: 'none' }} />
      <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 6, marginTop: 24 }}>
        <TextButton t={t} onClick={onClose}>{L.cancel}</TextButton>
        <FilledButton t={t} disabled={!v || v === iso} onClick={() => onSave(v)}>{L.changeDateBtn}</FilledButton>
      </div>
    </Dialog>
  );
}

function EditDialog({ t, L, project, onClose, onSave, onDelete }) {  const [title, setTitle] = useS(project.title);
  const [rows, setRows] = useS(project.rows.length);
  const [cols, setCols] = useS(project.minCols || 5);
  const [email, setEmail] = useS(project.email || '');
  return (
    <Dialog t={t} onClose={onClose}>
      <h2 style={{ margin: '0 0 18px', fontSize: 22, fontWeight: 600, color: t.onSurface }}>{L.editProject}</h2>
      <Field t={t} label={L.projectTitle} value={title} onChange={setTitle} />
      <div style={{ marginTop: 18 }}>
        <Field t={t} label={L.emailLabel} type="email" placeholder={L.emailHint} value={email} onChange={setEmail} />
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14, marginTop: 18 }}>
        <Stepper t={t} label={L.rows} value={rows} min={1} max={12} onChange={setRows} />
        <Stepper t={t} label={L.columns} value={cols} min={1} max={31} onChange={setCols} />
      </div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 24 }}>
        <TextButton t={t} tone="error" onClick={onDelete}>{L.delete}</TextButton>
        <div style={{ display: 'flex', gap: 6 }}>
          <TextButton t={t} onClick={onClose}>{L.cancel}</TextButton>
          <FilledButton t={t} disabled={!title.trim()} onClick={() => onSave({ title: title.trim(), rows, cols, email: email.trim() })}>{L.save}</FilledButton>
        </div>
      </div>
    </Dialog>
  );
}

function ProjectDetail({ t, L, lang, style, dens, project, onBack, onChange, onDelete, showMed }) {
  const [editing, setEditing] = useS(false);
  const [editCol, setEditCol] = useS(null);
  const scrollRef = useR(null);
  const todayIso = window.APP.dayOffset(0);
  const curMonth = window.APP.ymOf(todayIso);

  const dated = window.APP.monthDays(project, curMonth);
  const emptyCount = Math.max(0, (project.minCols || 5) - dated.length);
  const cols = dated.map((d) => ({ date: d })).concat(Array.from({ length: emptyCount }, () => ({ date: null })));

  const setStep = (s) => onChange({ ...project, step: s });
  const apply = (iso, rowId, delta) => {
    const k = kOf(iso, rowId); const next = Math.max(0, (project.counts[k] || 0) + delta);
    const counts = { ...project.counts }; if (next === 0) delete counts[k]; else counts[k] = next;
    onChange({ ...project, counts, updated: Date.now() });
  };
  const rename = (rowId, name) => onChange({ ...project, rows: project.rows.map((r) => r.id === rowId ? { ...r, name } : r) });
  // Reassign a logged column to a different date; counts move (and merge if the target already has data).
  const changeColDate = (oldIso, newIso) => {
    if (!newIso || newIso === oldIso) { setEditCol(null); return; }
    const days = project.days.filter((d) => d !== oldIso);
    const counts = { ...project.counts };
    project.rows.forEach((r) => {
      const ok = kOf(oldIso, r.id), nk = kOf(newIso, r.id);
      if (counts[ok] != null) { counts[nk] = (counts[nk] || 0) + counts[ok]; delete counts[ok]; }
    });
    if (!days.includes(newIso)) days.push(newIso);
    onChange({ ...project, days, counts, updated: Date.now() });
    setEditCol(null);
  };
  // Med: every tap logs for TODAY (the date the tap happens), kept in
  // project.medLog[isoDay][rowId]. The Entries cell shows the month total.
  const applyMed = (rowId, delta) => {
    const today = window.APP.dayOffset(0);
    const log = { ...(project.medLog || {}) };
    const day = { ...(log[today] || {}) };
    const next = Math.max(0, (day[rowId] || 0) + delta);
    if (next === 0) delete day[rowId]; else day[rowId] = next;
    if (Object.keys(day).length === 0) delete log[today]; else log[today] = day;
    onChange({ ...project, medLog: log, updated: Date.now() });
  };

  const scrollToCol = (idx) => setTimeout(() => { const el = scrollRef.current; if (!el) return; el.scrollTo({ left: Math.max(0, dens.rowLabelW + idx * dens.cellW - (el.clientWidth - dens.cellW) / 2), behavior: 'smooth' }); }, 40);
  const logToday = () => {
    if (project.days.includes(todayIso)) { scrollToCol(dated.indexOf(todayIso)); return; }
    const days = [...project.days, todayIso];
    onChange({ ...project, days, updated: Date.now() });
    scrollToCol(window.APP.monthDays({ ...project, days }, curMonth).indexOf(todayIso));
  };

  const saveEdit = ({ title, rows, cols: minCols, email }) => {
    let newRows = project.rows.slice();
    while (newRows.length < rows) newRows.push({ id: window.APP.uid('r'), name: L.rowDefault(newRows.length + 1) });
    const removed = newRows.slice(rows); newRows = newRows.slice(0, rows);
    const counts = { ...project.counts };
    removed.forEach((r) => Object.keys(counts).forEach((k) => { if (k.endsWith('|' + r.id)) delete counts[k]; }));
    onChange({ ...project, title, rows: newRows, minCols, email, counts, updated: Date.now() });
    setEditing(false);
  };

  let maxv = 1; dated.forEach((d) => project.rows.forEach((r) => { maxv = Math.max(maxv, project.counts[kOf(d, r.id)] || 0); }));
  const colTotal = (iso) => project.rows.reduce((s, r) => s + (project.counts[kOf(iso, r.id)] || 0), 0);
  const rowTotal = (rid) => dated.reduce((s, d) => s + (project.counts[kOf(d, rid)] || 0), 0);
  const grand = dated.reduce((s, d) => s + colTotal(d), 0);

  let medMax = 1; project.rows.forEach((r) => { medMax = Math.max(medMax, window.APP.medRowVal(project, r.id, curMonth)); });
  const medTotal = window.APP.medProjectTotal(project, curMonth);

  const headFill = t[style.headerFill] || t.surface;
  const headText = style.headerFill === 'primary' ? t.onPrimary : (style.headerFill === 'primaryContainer' ? t.onPrimaryContainer : t.onSurface);
  const TOTAL_W = 54, headerBg = style.gridLines ? t.surfContLow : t.surfCont;
  const MED_W = dens.cellW, medLeft = dens.rowLabelW;

  return (
    <div style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', background: t.surface }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 4, padding: '6px 6px 6px 4px', background: headFill, color: headText, flexShrink: 0 }}>
        <IconButton name="back" color={headText} onClick={onBack} label={L.cancel} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 21, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{project.title}</div>
          <div style={{ fontSize: 13, opacity: 0.85, textTransform: 'capitalize' }}>{window.APP.monthLong(curMonth, lang)}</div>
        </div>
        <IconButton name="edit" color={headText} onClick={() => setEditing(true)} label={L.edit} />
      </div>

      <div style={{ padding: '8px 16px 10px', flexShrink: 0 }}>
        <StepGroup t={t} L={L} style={style} value={project.step} onChange={setStep} />
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, marginTop: 11 }}>
          <span style={{ fontSize: 13, color: t.onSurfaceVariant, lineHeight: 1.3, flex: 1 }}>{L.tapHint}</span>
          <button onClick={logToday} style={{ display: 'flex', alignItems: 'center', gap: 7, border: 'none', cursor: 'pointer', background: t.secondaryContainer, color: t.onSecondaryContainer, padding: '9px 16px 9px 12px', borderRadius: 100, fontSize: 14.5, fontWeight: 600, flexShrink: 0, whiteSpace: 'nowrap' }}>
            <Icon name="today" size={18} color={t.onSecondaryContainer} /> {L.logToday}
          </button>
        </div>
      </div>

      <div ref={scrollRef} style={{ flex: 1, minHeight: 0, overflow: 'auto' }}>
        <div style={{ display: 'inline-grid', gridTemplateColumns: `${dens.rowLabelW}px ${showMed ? `${MED_W}px ` : ''}repeat(${cols.length}, ${dens.cellW}px) ${TOTAL_W}px` }}>
          <div style={{ position: 'sticky', top: 0, left: 0, zIndex: 5, background: headerBg, height: 58, display: 'flex', alignItems: 'flex-end', padding: '0 8px 8px 14px', boxSizing: 'border-box', borderRight: showMed ? `1px solid ${t.outlineVariant}55` : 'none' }}>
            <span style={{ fontSize: 13, fontWeight: 700, color: t.onSurfaceVariant, letterSpacing: 0.3 }}>{lang === 'es' ? 'Categoría' : 'Category'}</span>
          </div>
          {showMed && (
            <div style={{ position: 'sticky', top: 0, left: medLeft, zIndex: 6, background: headerBg, height: 58, display: 'flex', alignItems: 'flex-end', justifyContent: 'center', paddingBottom: 8, borderRight: `1px solid ${t.outlineVariant}55` }}>
              <span style={{ fontSize: 13, fontWeight: 700, color: t.primary, letterSpacing: 0.3 }}>Med</span>
            </div>
          )}
          {cols.map((col, ci) => {
            const isToday = col.date === todayIso; const f = col.date ? window.APP.fmtCol(col.date, lang) : null;
            return (
              <div key={col.date || 'e' + ci} onClick={col.date ? () => setEditCol(col.date) : undefined} style={{ position: 'sticky', top: 0, zIndex: 4, background: headerBg, height: 58, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 1, cursor: col.date ? 'pointer' : 'default' }}>
                {f ? (
                  <React.Fragment>
                    <span style={{ fontSize: 11.5, color: isToday ? t.primary : t.onSurfaceVariant, fontWeight: 600, textTransform: 'capitalize' }}>{f.wd}</span>
                    <span style={{ fontSize: 18, fontWeight: 700, lineHeight: 1, color: isToday ? t.onPrimary : t.onSurface, background: isToday ? t.primary : 'transparent', borderRadius: 100, minWidth: 26, height: 26, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{f.day}</span>
                  </React.Fragment>
                ) : <span style={{ fontSize: 20, color: t.onSurfaceVariant + '55', lineHeight: 1 }}>–</span>}
              </div>
            );
          })}
          <div style={{ position: 'sticky', top: 0, zIndex: 4, background: headerBg, height: 58, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <span style={{ fontSize: 13, fontWeight: 700, color: t.onSurfaceVariant }}>Σ</span>
          </div>

          {project.rows.map((r) => (
            <React.Fragment key={r.id}>
              <div style={{ position: 'sticky', left: 0, zIndex: 3, background: t.surface, borderRight: `1px solid ${t.outlineVariant}55` }}>
                <RowLabel t={t} dens={dens} name={r.name} onRename={(n) => rename(r.id, n)} />
              </div>
              {showMed && (
                <div style={{ position: 'sticky', left: medLeft, zIndex: 3, background: t.surface, borderRight: `1px solid ${t.outlineVariant}55`, display: 'flex' }}>
                  <Cell t={t} style={style} dens={dens} step={project.step}
                    value={window.APP.medRowVal(project, r.id, curMonth)} maxv={medMax} onApply={(d) => applyMed(r.id, d)} />
                </div>
              )}
              {cols.map((col, ci) => (
                <Cell key={col.date || 'e' + ci} t={t} style={style} dens={dens} step={project.step} disabled={!col.date}
                  value={col.date ? (project.counts[kOf(col.date, r.id)] || 0) : 0} maxv={maxv} onApply={(d) => apply(col.date, r.id, d)} />
              ))}
              <div style={{ height: dens.cellH, width: TOTAL_W, display: 'flex', alignItems: 'center', justifyContent: 'center', background: t.surfContLow, fontSize: dens.cellFont - 3, fontWeight: 700, color: t.primary }}>{rowTotal(r.id)}</div>
            </React.Fragment>
          ))}

          <div style={{ position: 'sticky', left: 0, bottom: 0, zIndex: 5, background: t.surfContHigh, height: 46, display: 'flex', alignItems: 'center', padding: '0 14px', borderRight: `1px solid ${t.outlineVariant}55` }}>
            <span style={{ fontSize: 14, fontWeight: 700, color: t.onSurface }}>{L.total}</span>
          </div>
          {showMed && (
            <div style={{ position: 'sticky', left: medLeft, bottom: 0, zIndex: 5, background: t.surfContHigh, height: 46, display: 'flex', alignItems: 'center', justifyContent: 'center', borderRight: `1px solid ${t.outlineVariant}55`, fontSize: 16, fontWeight: 800, color: t.primary }}>{medTotal}</div>
          )}
          {cols.map((col, ci) => (
            <div key={col.date || 'e' + ci} style={{ position: 'sticky', bottom: 0, zIndex: 4, background: t.surfContHigh, height: 46, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16, fontWeight: 700, color: col.date ? t.onSurface : t.onSurfaceVariant + '55' }}>{col.date ? colTotal(col.date) : '–'}</div>
          ))}
          <div style={{ position: 'sticky', bottom: 0, zIndex: 4, background: t.primaryContainer, height: 46, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16, fontWeight: 800, color: t.onPrimaryContainer }}>{grand}</div>
        </div>
      </div>

      <HSlider t={t} scrollRef={scrollRef} deps={[cols.length, dens.cellW, dens.rowLabelW]} />
      {editing && <EditDialog t={t} L={L} project={project} onClose={() => setEditing(false)} onSave={saveEdit} onDelete={onDelete} />}
      {editCol && <ColDateDialog t={t} L={L} iso={editCol} onClose={() => setEditCol(null)} onSave={(v) => changeColDate(editCol, v)} />}
    </div>
  );
}

Object.assign(window, { ProjectDetail, HSlider });
