import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './app/theme.css';
import { App } from './app/App';
import { ExplainProvider } from './app/explain-context';
import { PACKS } from './app/packs';
import { SessionProvider } from './app/session-context';
import { approveTerms } from './runtime/approvals';
import { recordPackExamples } from './runtime/signing';
import { AnchorProvider } from './app/anchor-context';
import { createAnchorStore } from './app/anchors';
import { generateSigningKey } from './ledger/chain';
import { createSession } from './runtime/session';
import { royaltyRules } from './packs/royalty';
import { createWorkerEvaluator } from './runtime/worker-evaluator';

const root = createRoot(document.getElementById('root')!);
root.render(<p className="boot">Loading…</p>);

const pack = PACKS[0];

// The rollup demo's operator key (plan ruling R28), generated once here and given to createSession
// (so it signs the session's real blocks) and to App, which provides it to the Ladder page alone (so its L3
// demo can play a SIMULATED dishonest operator under the same key). Nothing else sees the private key.
generateSigningKey()
  .then((operator) =>
    // requireApprovals: nothing is recorded until every party named on a
    // contract has signed the genesis terms (simulated keys); the session
    // refuses, and the revenue rail holds its record controls back meanwhile.
    // Evaluation runs in a Web Worker: at film scale a record takes seconds of rule evaluation.
    createSession(pack, { requireApprovals: true, operator, evaluator: createWorkerEvaluator(pack.rules ?? royaltyRules()) }).then((session) => ({ session, operator })),
  )
  .then(
    ({ session, operator }) => {
      // Simulated approvals (Task V5): opt-in, not part of createSession, so it
      // never affects any test or code path that just creates a session. Not
      // awaited — the app renders immediately, and the "Terms & approvals"
      // panel shows the signatures arriving until this resolves and the
      // session notifies its subscribers.
      void approveTerms(session).catch((err: unknown) => {
        console.error('simulated approvals failed', err);
      });
      // The pack's worked examples, each signed by the party it pays (simulated keys) and checked by the
      // rules in the worker before it is recorded (paper §7.5). Not awaited, like the approvals.
      void recordPackExamples(session).catch((err: unknown) => {
        console.error('recording the worked examples failed', err);
      });
      // The simulated anchor log: this tab's memory only (ledger/anchor.ts).
      const anchors = createAnchorStore();
      root.render(
        <StrictMode>
          <SessionProvider session={session}>
            <AnchorProvider store={anchors}>
              <ExplainProvider>
                <App operator={operator} />
              </ExplainProvider>
            </AnchorProvider>
          </SessionProvider>
        </StrictMode>,
      );
    },
    (err: unknown) => {
      console.error(err);
      root.render(
        <p className="boot boot--error" role="alert">
          Could not start the ledger: {err instanceof Error ? err.message : String(err)}
        </p>,
      );
    },
  );
