/* Nelawa — held.jsx: the ONE home for everything off the board.
   "If it's not on my board, it's in Held." A held task isn't lost or late —
   it's waiting, and the only thing that differs is what brings it back:
     • Coming back   — a date returns it, on its own, on the day (deferUntil).
     • Waiting        — blocked on a person/event; back when they respond.
     • Someday        — no date, no commitment; back only when you go looking.
   This view exists to reassure, not to prompt. No debt, no red, no overdue.
   Default is a calm glance (soonest returns + a scannable Waiting group);
   the long tail is a deliberate deeper tap, never a doom-scroll. */

function heldDaysUntil(iso) {
  const today = DumpUtil.todayISO();
  const a = new Date(today + 'T00:00:00');
  const b = new Date(iso + 'T00:00:00');
  return Math.round((b - a) / 86400000);
}
function heldRelWhen(iso) {
  const days = heldDaysUntil(iso);
  return days <= 0 ? 'today' : days === 1 ? 'tomorrow' : days < 7 ? 'in ' + days + ' days' : DumpUtil.dueLabel(iso);
}

/* Let-go is a conscious release, never shame — binned with a full undo that
   restores whatever group the item came from. */
function heldLetGo(task, restore) {
  DumpStore.set((s) => ({ tasks: s.tasks.map((t) => (t.id === task.id ? { ...t, status: 'binned', binnedAt: new Date().toISOString(), deferUntil: null } : t)) }));
  DumpAPI.toast('Let go — no guilt. In the bin if you want it back.', {
    action: { label: 'Undo', fn: () => DumpStore.set((s) => ({ tasks: s.tasks.map((t) => (t.id === task.id ? { ...t, binnedAt: null, ...restore } : t)) })) }
  });
}

/* ---------- Coming back (a date returns it) ---------- */
function ComingRow({ task }) {
  const [confirming, setConfirming] = useState(false);
  const when = heldRelWhen(task.deferUntil);

  const bringBack = () => {
    DumpAPI.bringBackHeld(task.id);
    DumpAPI.toast('Back on your board.', {
      action: { label: 'Undo', fn: () => DumpAPI.deferTask(task.id, task.deferUntil) }
    });
  };
  const makeDeadline = () => {
    DumpAPI.setDeadline(task.id, task.deferUntil);
    DumpAPI.toast('Now a deadline for ' + DumpUtil.dueLabel(task.deferUntil) + ' — on your board.');
  };
  const letGo = () => heldLetGo(task, { status: 'active', deferUntil: task.deferUntil });

  return (
    <div className="held-item">
      <div className="held-when" title={'Comes back ' + DumpUtil.dueLabel(task.deferUntil)}>
        <span className="held-when-day">{DumpUtil.dueLabel(task.deferUntil)}</span>
        <span className="held-when-rel">back {when}</span>
      </div>
      <div className="held-body">
        <p className="held-text">{task.text}</p>
        <div className="meta-row">
          <CatPill name={task.category} />
          <ChildChip childId={task.childId} />
        </div>
      </div>
      <div className="held-actions">
        {confirming ? (
          <React.Fragment>
            <span className="held-confirm-q">Let it go?</span>
            <button className="linklike" onClick={letGo}>Yes, let go</button>
            <button className="linklike" onClick={() => setConfirming(false)}>Keep</button>
          </React.Fragment>
        ) : (
          <div className="overflow-wrap held-menu-wrap">
            <button className="btn btn-ghost btn-sm" onClick={bringBack} title="Put it back on the board now">{Icons.check(13)} Bring back</button>
            <ComingMore onDeadline={makeDeadline} onLetGo={() => setConfirming(true)} />
          </div>
        )}
      </div>
    </div>
  );
}

function ComingMore({ onDeadline, onLetGo }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);
  return (
    <span className="overflow-wrap" ref={ref}>
      <button className="btn btn-ghost overflow-btn" aria-haspopup="true" aria-expanded={open} aria-label="More" onClick={() => setOpen((o) => !o)}>{Icons.more(16)}</button>
      {open ? (
        <div className="overflow-menu down" role="menu">
          <button role="menuitem" onClick={() => { setOpen(false); onDeadline(); }}>{Icons.flag(15)} Make it a deadline</button>
          <div className="menu-sep"></div>
          <button role="menuitem" onClick={() => { setOpen(false); onLetGo(); }}>{Icons.pause(15)} Let it go</button>
        </div>
      ) : null}
    </span>
  );
}

/* ---------- Waiting / Someday (no self-returning date) ---------- */
function ParkedRow({ task, kind }) {
  const [confirming, setConfirming] = useState(false);
  const isWaiting = kind === 'waiting';

  const toBoard = () => {
    const prev = { status: task.status, bucket: task.bucket, waitingOn: task.waitingOn };
    DumpStore.set((s) => ({ tasks: s.tasks.map((t) => (t.id === task.id ? { ...t, status: 'active', bucket: 'next-action', waitingOn: null, fresh: true } : t)) }));
    DumpAPI.toast(isWaiting ? 'Unblocked — back on your board.' : 'Back on your board.', {
      action: { label: 'Undo', fn: () => DumpStore.set((s) => ({ tasks: s.tasks.map((t) => (t.id === task.id ? { ...t, fresh: false, ...prev } : t)) })) }
    });
  };
  const letGo = () => heldLetGo(task, { status: task.status, bucket: task.bucket, waitingOn: task.waitingOn });

  return (
    <div className="held-item">
      <div className={'held-why held-why-' + kind}>
        {isWaiting ? Icons.hourglass(15) : Icons.pause(15)}
        <span className="held-why-label">{isWaiting ? 'Waiting' : 'Someday'}</span>
      </div>
      <div className="held-body">
        <p className="held-text">{task.text}</p>
        <div className="meta-row">
          <CatPill name={task.category} />
          <ChildChip childId={task.childId} />
          {isWaiting && task.waitingOn ? (
            <span className="due-chip" title={'Waiting on ' + task.waitingOn}>{Icons.hourglass(11)} {task.waitingOn}</span>
          ) : null}
        </div>
      </div>
      <div className="held-actions">
        {confirming ? (
          <React.Fragment>
            <span className="held-confirm-q">Let it go?</span>
            <button className="linklike" onClick={letGo}>Yes, let go</button>
            <button className="linklike" onClick={() => setConfirming(false)}>Keep</button>
          </React.Fragment>
        ) : (
          <div className="held-menu-wrap">
            <button className="btn btn-ghost btn-sm" onClick={toBoard} title={isWaiting ? 'They came back — put it on your board' : 'Pick it up — put it on your board'}>
              {Icons.check(13)} {isWaiting ? 'Unblock' : 'To board'}
            </button>
            <button className="linklike held-letgo" onClick={() => setConfirming(true)}>Let go</button>
          </div>
        )}
      </div>
    </div>
  );
}

/* ---------- A group shell: header + count + optional reassurance ---------- */
function HeldGroup({ icon, title, count, sub, children }) {
  return (
    <div className="held-group">
      <h2 className="held-group-h">{icon}<span className="held-group-title">{title}</span><span className="held-group-n">{count}</span></h2>
      {sub ? <p className="held-group-sub">{sub}</p> : null}
      {children}
    </div>
  );
}

const COMING_PREVIEW = 4;

function HeldSection() {
  const { tasks } = useDumpStore();
  const [showAllComing, setShowAllComing] = useState(false);
  const [showSomeday, setShowSomeday] = useState(false);
  const today = DumpUtil.todayISO();

  const notDone = (t) => !t.done && t.status !== 'binned';
  // Exactly one home each: a person-block wins over a stray date (the person is
  // the real blocker), and Someday is the dateless pile.
  const waiting = tasks.filter((t) => notDone(t) && t.status === 'waiting');
  const someday = tasks.filter((t) => notDone(t) && t.status === 'someday');
  const comingBack = tasks
    .filter((t) => notDone(t) && t.status !== 'waiting' && t.status !== 'someday' && t.deferUntil && t.deferUntil > today)
    .sort((a, b) => a.deferUntil.localeCompare(b.deferUntil));

  const total = comingBack.length + waiting.length + someday.length;

  const comingShown = showAllComing ? comingBack : comingBack.slice(0, COMING_PREVIEW);
  const comingHidden = comingBack.length - comingShown.length;

  return (
    <div className="section" data-screen-label="Held">
      <div className="section-head">
        <h1 className="section-title">Held</h1>
      </div>
      <p className="section-sub">
        {total
          ? 'Nothing’s lost. Everything off your board lives here — each with what brings it back.'
          : 'A quiet shelf for everything that isn’t for right now.'}
      </p>

      {total === 0 ? (
        <EmptyState icon={Icons.pause(26)} title="Nothing set aside">
          When something isn’t for right now — choose a day, mark it waiting on someone, or park it for someday. It waits here, off your mind, and only comes back when it should.
        </EmptyState>
      ) : (
        <div className="held-list">

          {comingBack.length ? (
            <HeldGroup
              icon={Icons.calendar(15)}
              title="Coming back"
              count={comingBack.length}
              sub={'Next back ' + heldRelWhen(comingBack[0].deferUntil) + ' — each returns on its own, on the day.'}>
              {comingShown.map((t) => <ComingRow key={t.id} task={t} />)}
              {comingHidden > 0 ? (
                <button className="held-more-link" onClick={() => setShowAllComing(true)}>
                  Show {comingHidden} more — next back {heldRelWhen(comingBack[COMING_PREVIEW].deferUntil)}
                </button>
              ) : null}
              {showAllComing && comingBack.length > COMING_PREVIEW ? (
                <button className="held-more-link" onClick={() => setShowAllComing(false)}>Show fewer</button>
              ) : null}
            </HeldGroup>
          ) : null}

          {waiting.length ? (
            <HeldGroup
              icon={Icons.hourglass(15)}
              title="Waiting on someone"
              count={waiting.length}
              sub="Blocked on a reply or an event — kept easy to scan so nothing slips.">
              {waiting.map((t) => <ParkedRow key={t.id} task={t} kind="waiting" />)}
            </HeldGroup>
          ) : null}

          {someday.length ? (
            <div className="held-group">
              <button className="held-group-toggle" aria-expanded={showSomeday} onClick={() => setShowSomeday((v) => !v)}>
                {Icons.pause(15)}
                <span className="held-group-title">Someday</span>
                <span className="held-group-n">{someday.length}</span>
                <span className="held-toggle-hint">{showSomeday ? 'Hide' : 'Show'}</span>
                <svg className={'held-chev' + (showSomeday ? ' up' : '')} width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M6 9l6 6 6-6"></path></svg>
              </button>
              <p className="held-group-sub">No date, no pressure — here only when you go looking.</p>
              {showSomeday ? someday.map((t) => <ParkedRow key={t.id} task={t} kind="someday" />) : null}
            </div>
          ) : null}

        </div>
      )}
    </div>
  );
}

window.HeldSection = HeldSection;
