// Dashboard → To-dos. The shared shell owns the h1.
function TodosPage() {
  const table = window.useTables(["todos"]);
  if (table.status === "loading") return <Loading />;
  if (table.status === "error") return <LoadError error={table.error} onRetry={table.reload} />;
  return <TodosList initialRows={table.data.todos} reload={table.reload} />;
}

function TodosList({ initialRows, reload }) {
  const todo = window.AreteTodos;
  const [rows, setRows] = React.useState(initialRows);
  const [title, setTitle] = React.useState("");
  const [due, setDue] = React.useState("");
  const [who, setWho] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState("");
  const [notice, setNotice] = React.useState("");
  const lock = React.useRef(false);
  const titleInput = React.useRef(null);
  const preview = window.isPreview();
  // Focus changes become visible when returning to this tab; don't interrupt a
  // draft or a pending write. A Refresh button is always available when idle.
  React.useEffect(() => {
    const refresh = () => { if (!lock.current && !title && !due && !who && !preview) reload(); };
    window.addEventListener("focus", refresh);
    return () => window.removeEventListener("focus", refresh);
  }, [title, due, who, preview, reload]);

  async function save(run) {
    if (lock.current || preview) return;
    lock.current = true; setBusy(true); setError(""); setNotice("");
    try { await run(); }
    catch { setError("Could not save. Your list was restored. Refresh to check before trying again."); }
    finally { lock.current = false; setBusy(false); }
  }
  async function add(event) {
    event.preventDefault();
    if (lock.current || preview) return;
    let fields;
    try { fields = todo.draft({ title, due, who }); }
    catch (e) { setError(e.message); return; }
    const temporary = { ...fields, id: "pending-add", source: "Added by you", done: false };
    await save(async () => {
      await todo.optimisticSave({ rows, next: [...rows, temporary], publish: setRows,
        write: () => window.supaClient.schema("public").rpc("arete_add_todo", fields),
        accept: saved => [...rows, saved] });
      setTitle(""); setDue(""); setWho(""); setNotice("To-do added.");
      titleInput.current?.focus();
    });
  }
  async function toggle(row) {
    await save(async () => {
      await todo.optimisticSave({ rows, next: todo.replaceTodo(rows, row.id, { ...row, done: !row.done }),
        publish: setRows,
        write: () => window.supaClient.schema("public").rpc("arete_set_todo_done", { id: row.id, done: !row.done }),
        accept: saved => todo.replaceTodo(rows, row.id, saved) });
      setNotice(row.done ? "To-do marked open." : "To-do marked done.");
    });
  }
  const sorted = todo.sortTodos(rows);
  return <section className="phase5 todos-page" aria-label="Rental to-dos">
    <form className="todo-add" onSubmit={add} aria-label="Add a to-do">
      <label className="todo-title-field">New to-do
        <input ref={titleInput} value={title} onChange={e => setTitle(e.target.value)} required maxLength={500}
          placeholder="Add a to-do for Ryan or Addie" disabled={busy || preview} />
      </label>
      <label>Due (optional)<input type="date" value={due} onChange={e => setDue(e.target.value)} disabled={busy || preview} /></label>
      <label>Who<select value={who} onChange={e => setWho(e.target.value)} disabled={busy || preview}>
        <option value="">Unassigned</option><option value="Ryan">Ryan</option><option value="Addie">Addie</option>
      </select></label>
      <button className="btn primary" type="submit" disabled={busy || preview || !title.trim()}>Add</button>
    </form>
    <div className="todo-tools">
      <span>{rows.filter(row => !row.done).length} open</span>
      <button className="linkbtn" type="button" disabled={busy} onClick={reload}>Refresh</button>
    </div>
    {preview && <p className="sub">Preview only. Sign in to add or check off to-dos.</p>}
    {error && <p className="err" role="alert">{error}</p>}
    <p className="sr" role="status" aria-live="polite">{busy ? "Saving…" : notice}</p>
    {!rows.length ? <NoData>No to-dos yet. Add one above.</NoData> : <div className="tcard">
      <ul className="todo-list" aria-label="To-dos, open items first" aria-busy={busy}>
        {sorted.map(row => <li key={row.id} className={"todo" + (row.done ? " done" : "")}>
          <button type="button" className="todo-check-target" role="checkbox" aria-checked={row.done}
            aria-label={(row.done ? "Mark open: " : "Mark done: ") + row.title}
            disabled={busy || preview} onClick={() => toggle(row)}>
            <span className="check" aria-hidden="true">{row.done ? "✓" : ""}</span>
          </button>
          <div className="todo-body"><div className="tt">{row.title}</div>
            <div className="tmeta"><span className="chip">{row.source}</span>
              {row.due && <span className="chip">Due {todo.fullDate(row.due)}</span>}
              <span className="chip">{row.who || "Unassigned"}</span>
              {row.done && <span>Done</span>}
            </div>
          </div>
        </li>)}
      </ul>
    </div>}
  </section>;
}
window.ARETE_PAGES = Object.assign(window.ARETE_PAGES || {}, { "dashboard/todos": TodosPage });
