/* Dump — calendar-day.jsx: Day detail — flowing list view.

   Not a time grid. A chronological list where:
   — anchor periods appear as hairline dividers (geography, not containers)
   — events and committed tasks are cards with a time label on the left
   — a "now" line floats between the last past item and next future item
   — any-time tasks sit in a quiet section at the top
   — overlapping items stack naturally; no column-splitting needed
*/

const CALD_FULL_DOW = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

function CalendarDay({ iso, byDate, anchors, onBack, onSelect, selected, closeSelect }) {
  const cdState = useDumpStore();
  const settings = cdState.settings;
  const plan = (cdState.dayPlan || {})[iso];
  const dx = settings.dx || {};
  const range = calRange(dx);
  const [winS, winE] = range;

  const [addText, setAddText] = useState('');
  const [addTime, setAddTime] = useState('');
  const [addOpen, setAddOpen] = useState(false);

  const d = calParse(iso);
  const allItems = byDate[iso] || [];
  // Day plan rows (confirmed scheduler suggestions — soft, not calendar items).
  const planRows = ((plan && plan.entries) || [])
    .map((e) => ({ e, t: cdState.tasks.find((t) => t.id === e.taskId) }))
    .filter((r) => r.t && !r.t.done && r.t.status !== 'binned');
  const plannedIds = {};
  planRows.forEach((r) => { plannedIds[r.t.id] = true; });
  const floating = allItems.filter((it) => it.start == null && !(it.task && plannedIds[it.task.id]));
  const timed = allItems.filter((it) => it.start != null);
  const dayAnchors = anchorsForDay(anchors, d);
  const cap = dayCapacity(d, allItems, anchors, range);

  /* anchor conflict check for quick-add time — uses dayAnchors (already in minutes) */
  const addAnchorConflict = (() => {
    if (!addTime) return null;
    const tp = addTime.split(':');
    const timeMin = (parseInt(tp[0],10)||0)*60 + (parseInt(tp[1],10)||0);
    for (const a of (dayAnchors || [])) {
      if (timeMin >= a.start && timeMin < a.start + (a.duration || 30)) return a;
    }
    return null;
  })();

  const isToday = iso === DumpUtil.todayISO();
  const freeHrs = Math.round((cap.free / 60) * 2) / 2;
  const capLabel = cap.frac >= 0.80 ? 'big day' : cap.frac >= 0.50 ? 'moderate day' : 'light day';

  const catOf = (it) => it.kind === 'task' ? DumpUtil.catColor(it.category, settings.categories) : null;

  /* current time in minutes (only for today) */
  const nowMin = isToday ? (() => {
    const n = new Date(); return n.getHours() * 60 + n.getMinutes();
  })() : null;

  /* build interleaved list: anchor dividers + timed items, sorted by time */
  const entries = [];

  dayAnchors.forEach((a) => {
    if (a.start < winE) {
      entries.push({ type: 'anchor', time: a.start, name: a.name, duration: a.duration });
    }
  });

  timed.forEach((it) => {
    entries.push({ type: 'item', time: it.start, item: it });
  });

  // planned tasks appear IN the timeline at their suggested time — dashed,
  // clearly softer than real items (they are intentions, not appointments)
  planRows.forEach(({ e, t }) => {
    const m = hmToMin(e.time);
    if (m != null) entries.push({ type: 'plan', time: m, text: t.text, reason: e.reason });
  });

  entries.sort((a, b) => {
    if (a.time !== b.time) return a.time - b.time;
    if (a.type === 'anchor' && b.type !== 'anchor') return -1;
    if (b.type === 'anchor' && a.type !== 'anchor') return 1;
    return 0;
  });

  /* weave in the "now" marker between past and future */
  const listItems = [];
  if (nowMin != null) {
    let placed = false;
    entries.forEach((e) => {
      if (!placed && e.time > nowMin) {
        listItems.push({ type: 'now' });
        placed = true;
      }
      listItems.push(e);
    });
    if (!placed) listItems.push({ type: 'now' });
  } else {
    listItems.push(...entries);
  }

  /* commit quick-add */
  const commitAdd = () => {
    const text = addText.trim();
    if (!text) { DumpAPI.toast('Give the task a few words first.'); return; }
    const t = {
      id: DumpUtil.uid(), text, category: 'Personal', level: 'normal', priority: false,
      notes: '', done: false, doneAt: null, dueDate: iso, minutes: null, big: false,
      status: 'active', bucket: 'next-action', waitingOn: null, binnedAt: null,
      calendarType: null, time: addTime || null, steps: null, outcome: null,
      source: 'manual', createdAt: new Date().toISOString(), fresh: false
    };
    DumpStore.set((s) => ({ tasks: [t].concat(s.tasks) }));
    const conflictMsg = addAnchorConflict ? ' · overlaps with ' + addAnchorConflict.name : '';
    DumpAPI.toast(addTime ? ('Added at ' + addTime + conflictMsg + '.') : 'Added — any time that day.');
    setAddText(''); setAddTime(''); setAddOpen(false);
  };

  const cancelAdd = () => { setAddText(''); setAddTime(''); setAddOpen(false); };

  const dow = CAL_DOW[(d.getDay() + 6) % 7];
  const fullDow = CALD_FULL_DOW[d.getDay()];
  const titleLabel = fullDow + ' ' + d.getDate() + ' ' + CAL_MONTHS[d.getMonth()];

  return (
    <div className="section cal-section cald" data-screen-label="Day detail">

      {/* Header */}
      <div className="cald-head">
        <button className="cald-back" onClick={onBack}>
          {Icons.chevL(17)} Week
        </button>
        <h1 className="cald-title">{titleLabel}</h1>
      </div>

      {/* Capacity sentence */}
      <p className="cald-cap">
        {isToday ? 'Today: ' : ''}<strong>~{freeHrs} hr{freeHrs === 1 ? '' : 's'} free</strong>
        <span className="cald-cap-label"> · {capLabel}</span>
        {cap.frac >= 0.90 ? <span className="cald-cap-flag"> · This is a big day</span> : null}
      </p>

      {/* Day plan — confirmed scheduler suggestions. Soft intentions with time
          hints; deliberately NOT calendar entries (calendar = hard landscape).
          The rows themselves sit in the timeline below at their times. */}
      {planRows.length ? (
        <div className="cald-plan slim">
          <span className="cph">{Icons.sparkle(13)} Plan for this day</span>
          <span className="cpn">suggestions, not appointments — dashed in the timeline</span>
          <button className="linklike" onClick={() => DumpAPI.clearDayPlan(iso)}>Clear plan</button>
        </div>
      ) : null}

      {/* Any-time tasks */}
      {floating.length > 0 && (
        <div className="cald-anytime">
          <div className="cald-anytime-head">
            <span className="cald-anytime-label">Any time</span>
            <button className="cald-suggest-times linklike"
              onClick={() => DumpAPI.openScheduler(iso)}
              title="Suggest times for these tasks">
              {Icons.sparkle(11)} Find times
            </button>
          </div>
          <div className="cald-anytime-chips">
            {floating.map((it, i) => {
              const cat = catOf(it);
              return (
                <button key={i}
                  className={'ds-chip is-task is-anytime'}
                  style={cat ? { borderLeftColor: cat.text } : {}}
                  onClick={() => onSelect(it)}
                  title={it.title}>
                  <span className="ds-chip-text">{it.title}</span>
                </button>
              );
            })}
          </div>
        </div>
      )}

      {/* Flowing list */}
      <div className="cald-list">
        {timed.length === 0 && (
          <div className="cald-empty">
            No appointments {isToday ? 'today' : 'this day'}.
          </div>
        )}

        {listItems.map((entry, idx) => {

          /* ── now marker ── */
          if (entry.type === 'now') {
            return (
              <div key="now" className="cald-now">
                <span className="cald-now-pip"></span>
                <span className="cald-now-label">now</span>
                <span className="cald-now-line"></span>
              </div>
            );
          }

          /* ── anchor ── */
          if (entry.type === 'anchor') {
            const endMin = entry.time + (entry.duration || 30);
            /* count timed items that fall within this anchor's window */
            const overlapCount = timed.filter(
              (it) => it.start >= entry.time && it.start < endMin
            ).length;
            return (
              <div key={'a' + idx} className="cald-anchor-row">
                <span className="cald-anchor-time">{minToHm(entry.time)}–{minToHm(endMin)}</span>
                <span className="cald-anchor-name">{entry.name}</span>
                {overlapCount > 0 ? <span className="cald-anchor-count">{overlapCount} item{overlapCount > 1 ? 's' : ''}</span> : null}
              </div>
            );
          }

          /* ── planned task (soft, dashed) ── */
          if (entry.type === 'plan') {
            return (
              <div key={'p' + idx} className="cald-item is-plan">
                <span className="ci-time">{minToHm(entry.time)}</span>
                <span className="ci-body">
                  <span className="ci-title">{entry.text}</span>
                  <span className="ci-meta plan">{Icons.sparkle(11)} planned — flexible{entry.reason ? ' · ' + entry.reason : ''}</span>
                </span>
              </div>
            );
          }

          /* ── event / task card ── */
            if (entry.type === 'item') {
            const it = entry.item;
            const isEvent = it.kind === 'event';
            const cat = catOf(it);
            const isPast = nowMin != null && (it.start + (it.duration || 30)) < nowMin;
            const borderCol = isEvent ? 'var(--cal-event)' : (cat ? cat.text : 'transparent');
            const metaCol = !isEvent && cat ? cat.text : null;
            const withinAnchor = dayAnchors.find(
              (a) => it.start >= a.start && it.start < a.start + (a.duration || 30)
            );

            return (
              <button key={'i' + idx}
                className={'cald-item' + (isEvent ? ' is-event' : ' is-task') + (isPast ? ' is-past' : '')}
                style={{ borderLeftColor: borderCol }}
                onClick={() => onSelect(it)}>
                <span className="ci-time">{minToHm(it.start)}</span>
                <span className="ci-body">
                  <span className="ci-title">{it.title}</span>
                  <span className="ci-meta" style={metaCol ? { color: metaCol } : {}}>
                    {isEvent ? 'Calendar event' : (it.category || 'Task')}
                    {withinAnchor ? <span className="ci-anchor-ctx"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg> during {withinAnchor.name}</span> : null}
                  </span>
                </span>
                <span className="ci-arrow">{Icons.chevR(14)}</span>
              </button>
            );
          }

          return null;
        })}
      </div>

      {/* Quick-add */}
      {addOpen ? (
        <div className="cald-quickadd">
          <div className="qa-row">
            <input className="qa-text" autoFocus value={addText}
              placeholder="What needs doing?"
              onChange={(e) => setAddText(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === 'Enter') commitAdd();
                if (e.key === 'Escape') cancelAdd();
              }} />
          </div>
          <div className="qa-row qa-controls">
            <label>Time</label>
            <input type="time" className="qa-time" value={addTime}
              onChange={(e) => setAddTime(e.target.value)} />
            {addTime ? <button className="linklike" onClick={() => setAddTime('')}>any time</button> : null}
            <span className="qa-spacer"></span>
            <button className="btn btn-sm btn-primary" onClick={commitAdd}>Add</button>
            <button className="btn btn-sm btn-ghost" onClick={cancelAdd}>Cancel</button>
          </div>
          {addAnchorConflict ? (
            <p className="dp-anchor-warn qa-anchor-warn">↔ This overlaps with your {addAnchorConflict.name} anchor.</p>
          ) : null}
        </div>
      ) : (
        <button className="btn btn-primary cald-addbtn" onClick={() => setAddOpen(true)}>
          + Add for {isToday ? 'today' : dow}
        </button>
      )}

      <CalDetail item={selected} onClose={closeSelect} />
    </div>
  );
}

window.CalendarDay = CalendarDay;
