import {
  SIMULATED_OWNER,
  eligibleBaseUnits,
  formatAmount,
  type V2Position,
} from "../data/simulation";
import { PositionCard } from "../components/PositionCard";
import {
  Badge,
  CodeBlock,
  DataSourceBlock,
  Panel,
  SolvencyBar,
  StandingDisclosures,
} from "../components/ui";
import { typedDataJson } from "../lib/eip712";
import type { MigrationController } from "../state/migration";

function StepActions({
  c,
  nextLabel,
  nextDisabled,
  showBack = true,
}: {
  c: MigrationController;
  nextLabel: string;
  nextDisabled?: boolean;
  showBack?: boolean;
}) {
  return (
    <div className="actions">
      {showBack && (
        <button type="button" className="btn btn-ghost" onClick={c.back} data-testid="back">
          Back
        </button>
      )}
      <div className="actions-spacer" />
      <button
        type="button"
        className="btn btn-primary"
        onClick={c.next}
        disabled={nextDisabled}
        data-testid="next"
      >
        {nextLabel}
      </button>
    </div>
  );
}

/* ---------------- 1. Landing ---------------- */

export function Landing({ c }: { c: MigrationController }) {
  return (
    <div className="stack fade-in" data-testid="screen-landing">
      <div>
        <div className="eyebrow">V2 → V3 migration · Base pilot</div>
        <h1>Move a position to V3 only if you choose to.</h1>
        <p className="lede">
          This console shows what a V2 → V3 migration would look like, position by
          position. Nothing here moves funds. Every position stays exactly where
          it is unless you explicitly opt it in, and V2 keeps running either way.
        </p>
      </div>

      <SolvencyBar scenario={c.scenario} />
      {c.blocked && <DataSourceBlock solvency={c.scenario.solvency} />}

      <div className="grid-2">
        <Panel title="What the pilot is" testId="panel-pilot">
          <ul className="list-clean">
            <li>Base only, chainId 8453. No other chain has V3 writes.</li>
            <li>Allowlisted accounts only. No public V3 write access.</li>
            <li>
              Hard per-contract caps at deploy: 100 USDC per partnership-bond
              side, 250 USDC per accountability bond, 250 USDC single mutual-aid
              payout, 2,500 USDC total vault deposits.
            </li>
            <li>Four weeks minimum, extendable. Guardian pause is always armed.</li>
          </ul>
        </Panel>
        <Panel title="What it is not" testId="panel-not">
          <ul className="list-clean">
            <li>
              Not insurance. <code>MutualAidPoolV3</code> is discretionary mutual
              aid — no policy, no entitlement, no guaranteed payout.
            </li>
            <li>Not an upgrade of V2. V2 contracts are immutable and stay as deployed.</li>
            <li>Not automatic. There is no default-on checkbox anywhere.</li>
            <li>Not a wallet. This build cannot sign or broadcast anything.</li>
          </ul>
        </Panel>
      </div>

      <Panel title="Standing disclosures">
        <StandingDisclosures />
      </Panel>

      <StepActions c={c} nextLabel="Compare V2 and V3" showBack={false} />
    </div>
  );
}

/* ---------------- 2. Compare ---------------- */

export function Compare({ c }: { c: MigrationController }) {
  return (
    <div className="stack fade-in" data-testid="screen-compare">
      <div>
        <div className="eyebrow">Step 2 · Side by side</div>
        <h2>Your V2 positions and their V3 equivalents</h2>
        <p>
          Read-only. Positions without a V3 equivalent during the pilot are marked{" "}
          <em>stays in V2</em>. Amounts above a pilot cap remain in V2 for the
          excess.
        </p>
      </div>

      <SolvencyBar scenario={c.scenario} />
      {c.blocked && <DataSourceBlock solvency={c.scenario.solvency} />}

      <div className="table-wrap">
        <table data-testid="compare-table">
          <caption className="small" style={{ captionSide: "bottom", padding: "10px 14px", textAlign: "left" }}>
            All addresses are simulation placeholders. The repository has no
            validated V3 deployment addresses yet.
          </caption>
          <thead>
            <tr>
              <th scope="col">Position</th>
              <th scope="col">V2 today</th>
              <th scope="col">V3 during pilot</th>
              <th scope="col">Cap · eligible</th>
              <th scope="col">Reversible</th>
            </tr>
          </thead>
          <tbody>
            {c.positions.map((p) => (
              <tr key={p.id} data-testid={`compare-row-${p.id}`}>
                <th scope="row" style={{ fontWeight: 600 }}>
                  {p.label}
                </th>
                <td>
                  <div className="mono">{p.v2Contract}</div>
                  <div className="mono">{p.v2Address}</div>
                  <div>
                    {formatAmount(p.amountBaseUnits, p.assetDecimals)} {p.assetSymbol} ·
                    unchanged
                  </div>
                </td>
                <td>
                  {p.v3 ? (
                    <>
                      <div className="mono">{p.v3.contract}</div>
                      <div className="mono">{p.v3.address}</div>
                      <div className="small">simulated address</div>
                    </>
                  ) : (
                    <Badge tone="warn">no V3 equivalent — stays in V2</Badge>
                  )}
                </td>
                <td>
                  {p.v3 ? (
                    <>
                      <div>{p.v3.capLabel}</div>
                      <div className="mono">
                        {formatAmount(eligibleBaseUnits(p), p.assetDecimals)}{" "}
                        {p.assetSymbol} eligible
                      </div>
                    </>
                  ) : (
                    <span className="mono">—</span>
                  )}
                </td>
                <td>
                  {p.v3 ? (
                    p.v3.reversible ? (
                      <Badge tone="accent">reversible in pilot</Badge>
                    ) : (
                      <Badge tone="danger">irreversible</Badge>
                    )
                  ) : (
                    <span className="mono">—</span>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <StepActions c={c} nextLabel="Choose positions" />
    </div>
  );
}

/* ---------------- 3. Choose ---------------- */

export function Choose({ c }: { c: MigrationController }) {
  const optedIn = c.selectedPositions.length;
  return (
    <div className="stack fade-in" data-testid="screen-choose">
      <div>
        <div className="eyebrow">Step 3 · Explicit opt-in</div>
        <h2>Choose what, if anything, moves</h2>
        <p>
          Every checkbox starts unchecked. Leaving this screen untouched keeps all{" "}
          {c.positions.length} positions in V2 exactly as they are — that is a
          valid, complete outcome.
        </p>
      </div>

      <SolvencyBar scenario={c.scenario} />
      {c.blocked && <DataSourceBlock solvency={c.scenario.solvency} />}

      <div
        className="notice"
        data-testid="selection-summary"
        aria-live="polite"
      >
        <strong data-testid="selection-count">
          {optedIn === 0
            ? "0 positions opted in — everything stays in V2"
            : `${optedIn} of ${c.positions.length} positions opted in to V3`}
        </strong>
        <p style={{ marginTop: 4 }}>
          {c.keptPositions.length} position
          {c.keptPositions.length === 1 ? "" : "s"} will remain in V2, unchanged.
        </p>
      </div>

      <div>
        {c.positions.map((p) => (
          <PositionCard
            key={p.id}
            position={p}
            selected={c.state.selected.includes(p.id)}
            blocked={c.blocked}
            onToggle={c.toggle}
          />
        ))}
      </div>

      <div className="actions">
        <button type="button" className="btn btn-ghost" onClick={c.back} data-testid="back">
          Back
        </button>
        <button
          type="button"
          className="btn"
          onClick={c.keepAll}
          disabled={c.blocked || optedIn === 0}
          data-testid="keep-all-v2"
        >
          Reset — keep everything in V2
        </button>
        <div className="actions-spacer" />
        <button
          type="button"
          className="btn btn-primary"
          onClick={c.next}
          disabled={c.blocked || optedIn === 0}
          data-testid="next"
        >
          Review typed data
        </button>
      </div>
      {optedIn === 0 && !c.blocked && (
        <p className="small" data-testid="no-selection-hint">
          Nothing selected, so there is nothing to sign. You can close this page
          and your V2 positions are unaffected.
        </p>
      )}
    </div>
  );
}

/* ---------------- 4. Review ---------------- */

export function Review({ c }: { c: MigrationController }) {
  const json = typedDataJson(c.typedData);
  const irreversible = c.selectedPositions.filter((p) => p.v3 && !p.v3.reversible);
  return (
    <div className="stack fade-in" data-testid="screen-review">
      <div>
        <div className="eyebrow">Step 4 · Exact payload</div>
        <h2>The EIP-712 typed data, verbatim</h2>
        <p>
          This is the complete payload a wallet would be asked to sign — domain,
          types, and message, nothing hidden and nothing added at signing time.
          It is generated deterministically from your selection, so the same
          selection always produces the same bytes.
        </p>
      </div>

      {c.blocked ? (
        <DataSourceBlock solvency={c.scenario.solvency} />
      ) : (
        <>
          <Panel title="Domain" testId="panel-domain">
            <dl className="kv" data-testid="domain-kv">
              <dt>name</dt>
              <dd>{c.typedData.domain.name}</dd>
              <dt>version</dt>
              <dd>{c.typedData.domain.version}</dd>
              <dt>chainId</dt>
              <dd data-testid="domain-chainid">{c.typedData.domain.chainId}</dd>
              <dt>verifyingContract</dt>
              <dd data-testid="domain-verifying">
                {c.typedData.domain.verifyingContract}
              </dd>
              <dt>signer (demo)</dt>
              <dd>{SIMULATED_OWNER}</dd>
            </dl>
            <p className="small" style={{ marginTop: 10 }}>
              <Badge tone="warn">simulation data</Badge> The verifying contract and
              signer are fake placeholders. Domain <code>name</code> and{" "}
              <code>version</code> match <code>EIP712BaseV3.sol</code>.
            </p>
          </Panel>

          {irreversible.length > 0 && (
            <div className="notice notice-danger" role="alert" data-testid="irreversible-warning">
              <h3>Irreversible step selected</h3>
              <p>
                {irreversible.map((p) => p.label).join(", ")} cannot be undone
                inside the pilot window. Your V2 position is still untouched, but
                a V3 deposit would mint new shares at the V3 price.
              </p>
            </div>
          )}

          <CodeBlock
            label="EIP-712 typed data (deterministic)"
            code={json}
            testId="typed-data-json"
          />

          <Panel title="Digest" testId="panel-digest">
            <dl className="kv">
              <dt>keccak256 digest</dt>
              <dd data-testid="digest">{c.digest}</dd>
              <dt>positions in message</dt>
              <dd data-testid="message-position-count">
                {c.typedData.message.positions.length}
              </dd>
              <dt>keepV2Live</dt>
              <dd data-testid="keep-v2-live">
                {String(c.typedData.message.keepV2Live)}
              </dd>
            </dl>
            <p className="small" style={{ marginTop: 10 }}>
              Computed locally with keccak256 over the encoded struct. No RPC call
              and no wallet is involved.
            </p>
          </Panel>
        </>
      )}

      <StepActions
        c={c}
        nextLabel="Go to signing simulation"
        nextDisabled={c.blocked || c.selectedPositions.length === 0}
      />
    </div>
  );
}

/* ---------------- 5. Sign ---------------- */

export function Sign({ c }: { c: MigrationController }) {
  const canSign = !c.blocked && c.selectedPositions.length > 0;
  return (
    <div className="stack fade-in" data-testid="screen-sign">
      <div>
        <div className="eyebrow">Step 5 · Simulation</div>
        <h2>Signing simulation</h2>
        <p>
          This build has no wallet connection and no transport. Pressing the
          button below runs a local, deterministic stand-in so you can see the
          shape of the result. It does not request a signature, does not touch any
          injected provider, and does not broadcast anything.
        </p>
      </div>

      {c.blocked && <DataSourceBlock solvency={c.scenario.solvency} />}

      <Panel title="What would be signed" testId="panel-sign-summary">
        <dl className="kv">
          <dt>positions</dt>
          <dd data-testid="sign-position-count">{c.selectedPositions.length}</dd>
          <dt>digest</dt>
          <dd>{c.digest}</dd>
          <dt>chain</dt>
          <dd>Base · 8453</dd>
          <dt>method</dt>
          <dd>none — simulation only</dd>
        </dl>
        <ul className="list-clean" style={{ marginTop: 12 }}>
          {c.selectedPositions.map((p: V2Position) => (
            <li key={p.id}>
              {p.label} → {p.v3?.contract} ·{" "}
              {formatAmount(eligibleBaseUnits(p), p.assetDecimals)} {p.assetSymbol}
            </li>
          ))}
        </ul>
      </Panel>

      <div className="notice notice-warn" data-testid="no-broadcast-notice">
        <h3>No wallet, no broadcast, no keys</h3>
        <p>
          Even in the real product, migration is two independent transactions you
          send yourself. This console would only ever hand the payload to your
          wallet; it would never hold a key, and it would never submit for you.
        </p>
      </div>

      <div className="actions">
        <button type="button" className="btn btn-ghost" onClick={c.back} data-testid="back">
          Back
        </button>
        <div className="actions-spacer" />
        <button
          type="button"
          className="btn btn-primary"
          onClick={c.simulateSign}
          disabled={!canSign}
          data-testid="simulate-sign"
        >
          Run signing simulation
        </button>
      </div>
    </div>
  );
}

/* ---------------- 6. Confirm ---------------- */

export function Confirm({ c }: { c: MigrationController }) {
  return (
    <div className="stack fade-in" data-testid="screen-confirm">
      <div>
        <div className="eyebrow">Step 6 · Result</div>
        <h2>Simulated intent recorded locally</h2>
        <p>
          Nothing left this page. The payload below is what your wallet would have
          returned. No transaction exists on Base or anywhere else.
        </p>
      </div>

      <div className="notice notice-accent" data-testid="confirm-banner">
        <h3>V2 is unchanged</h3>
        <p>
          All {c.positions.length} V2 positions are exactly as they were before you
          opened this page. {c.selectedPositions.length} position
          {c.selectedPositions.length === 1 ? "" : "s"} would move to V3 in the
          real flow, in steps you would send yourself.
        </p>
      </div>

      <div className="grid-2">
        <Panel title="Would move to V3" testId="panel-moved">
          {c.selectedPositions.length === 0 ? (
            <p>None.</p>
          ) : (
            <ul className="list-clean" data-testid="confirm-moved-list">
              {c.selectedPositions.map((p) => (
                <li key={p.id}>
                  {p.label} → {p.v3?.contract}{" "}
                  {p.v3 && !p.v3.reversible && <Badge tone="danger">irreversible</Badge>}
                </li>
              ))}
            </ul>
          )}
        </Panel>
        <Panel title="Stays in V2" testId="panel-kept">
          <ul className="list-clean" data-testid="confirm-kept-list">
            {c.keptPositions.map((p) => (
              <li key={p.id}>
                {p.label} — {p.v3 ? "kept by choice" : "no V3 equivalent"}
              </li>
            ))}
          </ul>
        </Panel>
      </div>

      <Panel title="Simulated signature" testId="panel-signature">
        <dl className="kv">
          <dt>digest</dt>
          <dd data-testid="confirm-digest">{c.digest}</dd>
          <dt>signature</dt>
          <dd data-testid="confirm-signature">{c.signature ?? "—"}</dd>
          <dt>broadcast</dt>
          <dd data-testid="confirm-broadcast">none — simulation only</dd>
        </dl>
        <p className="small" style={{ marginTop: 10 }}>
          <Badge tone="warn">not a real signature</Badge> Derived deterministically
          from the digest for demonstration. It recovers to no address and is
          rejected by <code>SignatureVerifierV3</code>.
        </p>
      </Panel>

      <Panel title="Standing disclosures">
        <StandingDisclosures />
      </Panel>

      <div className="actions">
        <button type="button" className="btn" onClick={c.restart} data-testid="restart">
          Start over
        </button>
      </div>
    </div>
  );
}
