/* Dump — sweep.jsx: the Sunday sweep (GTD Reflect, 5-minute edition).
   One stale task at a time, one tap each: Keep / Done / Someday / Toss.
   Then a pass over Waiting and Someday so nothing rots. */

function sweepDue() {
  const s = DumpStore.getState();
  const total = s.tasks.filter((t) => !t.done && t.status !== 'binned').length;
  const days = DumpUtil.daysSince(s.lastSweep);
  if (!s.lastSweep) return total >= 5;
  const isSunday = new Date().getDay() === 0;
  return days >= 7 || (isSunday && days >= 3);
}

function buildSweepQueue() {
  const s = DumpStore.getState();
  const staleBefore = Date.now() - 3 * 86400000;
  const active = s.tasks
    .filter((t) => isActiveTask(t) && !t.trackDaily && new Date(t.createdAt || 0).getTime() < staleBefore)
    .sort((a, b) => (a.createdAt || '').localeCompare(b.createdAt || ''))
    .map((t) => ({ id: t.id, kind: 'active' }));
  const waiting = s.tasks.filter((t) => !t.done && t.status === 'waiting').map((t) => ({ id: t.id, kind: 'waiting' }));
  const someday = s.tasks.filter((t) => !t.done && t.status === 'someday').map((t) => ({ id: t.id, kind: 'someday' }));
  return active.concat(waiting, someday);
}

function startSweep() {
  if (!buildSweepQueue().length) {
    DumpAPI.toast('Nothing to sweep — the list is fresh and the garden is tidy.');
    DumpStore.set({ lastSweep: new Date().toISOString() });
    return;
  }
  DumpStore.set({ sweepOpen: true });
}

function SweepNudge() {
  const state = useDumpStore();
  const [dismissed, setDismissed] = useState(false);
  if (dismissed || state.sweepOpen || !sweepDue()) return null;
  return (
    <Banner icon={Icons.sweep(17)} onClose={() => setDismissed(true)}>
      Time for your weekly sweep — five minutes, one tap per task, and the list is honest again.{' '}
      <button className="linklike" onClick={startSweep}>Start the sweep →</button>
    </Banner>
  );
}

const SWEEP_ACTIONS = {
  active: [
    { key: 'done', label: 'Already done', hint: 'tick it off', weight: 'prim' },
    { key: 'keep', label: 'Keep', hint: 'still matters', weight: 'ghost' },
    { key: 'toss', label: 'Toss', hint: 'bin for 30 days', danger: true },
    { key: 'park', label: 'Move to Someday', hint: 'not now', demote: true }
  ],
  waiting: [
    { key: 'done', label: 'Resolved', hint: 'it happened', weight: 'prim' },
    { key: 'keep', label: 'Still waiting', hint: 'leave it be', weight: 'ghost' },
    { key: 'toss', label: 'Toss', hint: 'let it go', danger: true },
    { key: 'board', label: 'Back on the board', hint: 'chase it yourself', demote: true }
  ],
  someday: [
    { key: 'done', label: 'Already done', hint: 'tick it off', weight: 'prim' },
    { key: 'board', label: 'Back on the board', hint: 'time has come', weight: 'ghost' },
    { key: 'toss', label: 'Toss', hint: 'admit it\u2019s never', danger: true },
    { key: 'keep', label: 'Still someday', hint: 'not yet', demote: true }
  ]
};

function SweepFlow() {
  const [queue] = useState(buildSweepQueue);
  const [idx, setIdx] = useState(0);
  const [counts, setCounts] = useState({ kept: 0, board: 0, done: 0, parked: 0, tossed: 0 });
  const [anim, setAnim] = useState('');

  const finished = idx >= queue.length;

  useEffect(() => {
    if (finished && queue.length) {
      DumpStore.set({ lastSweep: new Date().toISOString() });
    }
  }, [finished]);

  const close = () => DumpStore.set({ sweepOpen: false });

  useEffect(() => {
    const onEsc = (e) => { if (e.key === 'Escape') close(); };
    document.addEventListener('keydown', onEsc);
    return () => document.removeEventListener('keydown', onEsc);
  }, []);

  const current = !finished ? queue[idx] : null;
  const task = current ? DumpStore.getState().tasks.find((t) => t.id === current.id) : null;

  const decide = (action) => {
    if (!task) { setIdx(idx + 1); return; }
    const id = task.id;
    if (action === 'done') {
      const doneAt = new Date().toISOString();
      DumpStore.set((s) => {
        const t = s.tasks.find((x) => x.id === id);
        return t ? {
          tasks: s.tasks.filter((x) => x.id !== id),
          archive: [{ ...t, done: true, doneAt, status: 'active' }, ...s.archive],
          focus: { ...s.focus, ids: s.focus.ids.filter((x) => x !== id) }
        } : {};
      });
      setCounts((c) => ({ ...c, done: c.done + 1 }));
    } else if (action === 'park') {
      DumpStore.set((s) => ({
        tasks: s.tasks.map((t) => (t.id === id ? { ...t, status: 'someday', waitingOn: null } : t)),
        focus: { ...s.focus, ids: s.focus.ids.filter((x) => x !== id) }
      }));
      setCounts((c) => ({ ...c, parked: c.parked + 1 }));
    } else if (action === 'board') {
      DumpStore.set((s) => ({
        tasks: s.tasks.map((t) => (t.id === id ? { ...t, status: 'active', waitingOn: null } : t))
      }));
      setCounts((c) => ({ ...c, board: c.board + 1 }));
    } else if (action === 'toss') {
      DumpStore.set((s) => ({
        tasks: s.tasks.map((t) => (t.id === id ? { ...t, status: 'binned', binnedAt: new Date().toISOString() } : t)),
        focus: { ...s.focus, ids: s.focus.ids.filter((x) => x !== id) }
      }));
      setCounts((c) => ({ ...c, tossed: c.tossed + 1 }));
    } else {
      setCounts((c) => ({ ...c, kept: c.kept + 1 }));
    }
    setAnim('out');
    setTimeout(() => { setIdx((i) => i + 1); setAnim('in'); }, 180);
  };

  const age = task && task.createdAt
    ? Math.max(0, Math.floor((Date.now() - new Date(task.createdAt).getTime()) / 86400000))
    : null;

  const summaryBits = [];
  if (counts.kept) summaryBits.push('kept ' + counts.kept);
  if (counts.board) summaryBits.push(counts.board + ' back on the board');
  if (counts.done) summaryBits.push(counts.done + ' already done');
  if (counts.parked) summaryBits.push('parked ' + counts.parked);
  if (counts.tossed) summaryBits.push('tossed ' + counts.tossed);

  return (
    <React.Fragment>
      <div className="overlay" style={{ zIndex: 70 }}></div>
      <div className="sweep-modal" role="dialog" aria-label="Weekly sweep">
        <div className="sweep-head">
          <h2>{Icons.sweep(19)} Sweep</h2>
          {!finished ? <span className="sweep-count">{idx + 1} of {queue.length}</span> : null}
          <button className="icon-btn" onClick={close} aria-label="Close sweep">{Icons.x(18)}</button>
        </div>
        <div className="sweep-prog"><span style={{ width: (finished ? 100 : (idx / queue.length) * 100) + '%' }}></span></div>

        {finished ? (
          <div className="sweep-body">
            <p className="sweep-done-title">Swept {queue.length} — {summaryBits.join(', ') || 'all reviewed'}.</p>
            <p className="sweep-hint">The list is honest again. One more move makes the week easy:</p>
            <div className="sweep-finish-actions">
              <button className="btn btn-primary" onClick={() => { close(); DumpStore.set({ route: 'tasks', tasksView: 'board' }); }}>
                Pick today's 3 →
              </button>
              <button className="btn btn-ghost" onClick={close}>Close</button>
            </div>
          </div>
        ) : task ? (
          <div className="sweep-body" key={idx}>
            {idx === 0 ? (
              <ContextHint id="hint-sweep-first" icon={Icons.sweep(16)}>
                The weekly Sweep is a five-minute honesty pass — one quick tap per task. It reviews Waiting, Someday, and anything on the board older than a few days (fresh tasks are left alone).
              </ContextHint>
            ) : null}
            <p className="sweep-kind">
              {current.kind === 'waiting' ? 'On the waiting list' : current.kind === 'someday' ? 'Parked under Someday' : 'On the board'}
            </p>
            <div className={'sweep-card' + (anim === 'out' ? ' sweep-out' : '')}>
              <p className="sweep-task-text">{task.text}</p>
              <div className="meta-row">
                <CatPill name={task.category} />
                {age !== null ? <span className="src-tag">added {age === 0 ? 'today' : age + ' day' + (age === 1 ? '' : 's') + ' ago'}</span> : null}
                {current.kind === 'waiting' && task.waitingOn ? <span className="due-chip">{Icons.hourglass(11)} {task.waitingOn}</span> : null}
                {task.dueDate ? <span className="due-chip">{Icons.calendar(11)} {DumpUtil.dueLabel(task.dueDate)}</span> : null}
              </div>
            </div>
            <p className="sweep-hint sweep-hint-top">One honest tap. Don’t overthink it — that’s the whole trick.</p>
            <div className="sweep-actions">
              {SWEEP_ACTIONS[current.kind].filter((a) => !a.demote).map((a) => (
                <button key={a.key} className={'btn sweep-btn' + (a.danger ? ' danger' : a.weight === 'prim' ? ' sweep-prim' : ' sweep-ghost')} onClick={() => decide(a.key)}>
                  <span className="sweep-btn-label">{a.label}</span>
                  <span className="sweep-btn-hint">{a.hint}</span>
                </button>
              ))}
            </div>
            {SWEEP_ACTIONS[current.kind].filter((a) => a.demote).map((a) => (
              <button key={a.key} className="linklike sweep-demote" onClick={() => decide(a.key)}>{a.label} · {a.hint}</button>
            ))}
          </div>
        ) : (
          // Task vanished mid-sweep (completed elsewhere) — skip ahead
          <div className="sweep-body">
            <p className="sweep-hint">That one's already gone — moving on.</p>
            <button className="btn btn-ghost" onClick={() => setIdx(idx + 1)}>Next</button>
          </div>
        )}
      </div>
    </React.Fragment>
  );
}

function SweepModal() {
  const { sweepOpen } = useDumpStore();
  if (!sweepOpen) return null;
  return <SweepFlow />;
}

Object.assign(window, { SweepModal, SweepNudge, startSweep, sweepDue });
