import React, { useEffect, useState } from 'react';
import { api, pending, write, parseState, type Command, type State } from './outbox';
export function App() {
  const [confirmed, setConfirmed] = useState<State>({ title: 'Initial', version: 0 });
  const [commands, setCommands] = useState<Command[]>([]);
  const [title, setTitle] = useState(''); const [message, setMessage] = useState('');
  const [busy, setBusy] = useState(false); const [lose, setLose] = useState(false);
  async function refresh() {
    setCommands(await pending());
    try { setConfirmed(parseState(await (await fetch(api)).json())); }
    catch (_) { setMessage('Offline: pending intent is retained'); }
  }
  useEffect(() => { void refresh(); }, []);
  async function save() {
    if (!title.trim() || commands.length || busy) return;
    setBusy(true);
    try {
      await write({ id: crypto.randomUUID(), title: title.trim(), version: confirmed.version });
      setCommands(await pending()); setTitle(''); setMessage('Intent stored before sending');
    } catch (_) { setMessage('Cannot persist intent'); }
    finally { setBusy(false); }
  }
  async function replay() {
    if (busy) return; setBusy(true);
    try {
      for (const command of await pending()) {
        const response = await fetch(api + (lose ? '?lose-response=1' : ''), {
          method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(command),
        });
        const state = parseState(await response.json());
        setConfirmed(state);
        if (response.status === 412) { setMessage('Conflict: compare server and pending title'); return; }
        if (!response.ok) throw new Error('Command rejected');
        await write(null, command.id);
      }
      setMessage('Confirmed');
    } catch (_) { setMessage('Reply missing: retry the same stored command'); }
    finally { setCommands(await pending()); setBusy(false); }
  }
  async function rebase() {
    if (!commands.length || busy) return;
    const old = commands[0];
    await write({ ...old, id: crypto.randomUUID(), version: confirmed.version }, old.id);
    setCommands(await pending()); setMessage('New intent stored against current version');
  }
  return <main><h1>Durable intent</h1>
    <p>Server: {confirmed.title}, version {confirmed.version}</p>
    <p>Optimistic: {commands[0]?.title ?? confirmed.title}</p>
    <label>Title<input value={title} onChange={event => setTitle(event.target.value)} /></label>
    <button disabled={busy || commands.length > 0} onClick={() => void save()}>Store intent</button>
    <button disabled={busy || !commands.length} onClick={() => void replay()}>Replay</button>
    <label><input type="checkbox" checked={lose} onChange={event => setLose(event.target.checked)} />Fail first reply</label>
    <button disabled={busy || !commands.length} onClick={() => void rebase()}>Apply mine to current version</button>
    <p role="status">{message}</p><p>Pending: {commands.length}</p>
  </main>;
}
