'use client';

/**
 * /erc8128 — Sign an HTTP request from your wallet using ERC-8128 and hit
 * theloopbreaker.com's /api/agent/premium gated endpoint live.
 *
 * Spec: https://ethereum-magicians.org/t/erc-8128-signed-http-requests-with-ethereum/
 * RFC : https://datatracker.ietf.org/doc/rfc9421/
 *
 * Sprint 4 demo (April 2026). Uses @slicekit/erc8128 directly (no SDK
 * dependency on this app side) so the demo stays self-contained.
 */

import { Header } from '@/components/Header';
import Link from 'next/link';
import { useState, useRef, useEffect } from 'react';
import { useAccount, useWalletClient } from 'wagmi';
import { signRequest, formatKeyId, type EthHttpSigner } from '@slicekit/erc8128';
import { hexToBytes, type Address, type Hex } from 'viem';

const PREMIUM_URL = 'https://theloopbreaker.com/api/agent/premium';
const VAULTFIRE_CHAIN_ID = 8453;

type SignedHeaders = {
  signature: string;
  signatureInput: string;
  contentDigest: string | null;
};

type ResponsePayload = {
  status: number;
  statusText: string;
  json: any;
};

export default function Erc8128DemoPage() {
  const { address, isConnected } = useAccount();
  const { data: walletClient } = useWalletClient();

  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [signedHeaders, setSignedHeaders] = useState<SignedHeaders | null>(null);
  const [response, setResponse] = useState<ResponsePayload | null>(null);
  const [bodyText, setBodyText] = useState<string>('');
  const responseRef = useRef<HTMLDivElement | null>(null);

  // Auto-scroll to the response banner whenever a new response lands
  useEffect(() => {
    if (response && responseRef.current) {
      responseRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }
  }, [response]);

  // Build a viem-backed EthHttpSigner that signs a Uint8Array as an EIP-191 message.
  function buildSigner(addr: Address): EthHttpSigner {
    if (!walletClient) throw new Error('Wallet client not ready');
    return {
      address: addr.toLowerCase() as Address,
      chainId: VAULTFIRE_CHAIN_ID,
      signMessage: async (message: Uint8Array): Promise<Hex> => {
        // viem applies the EIP-191 prefix — same as ethers.signMessage(bytes)
        const sig = await walletClient.signMessage({
          account: addr,
          message: { raw: message },
        });
        return sig as Hex;
      },
    };
  }

  async function handleSendSigned() {
    if (!address || !walletClient) return;
    setBusy(true);
    setError(null);
    setSignedHeaders(null);
    setResponse(null);

    try {
      const body = JSON.stringify({
        action: 'fetch_premium',
        timestamp: Date.now(),
        from: address,
      });
      setBodyText(body);

      const baseReq = new Request(PREMIUM_URL, {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body,
      });

      const signer = buildSigner(address as Address);
      const signed = await signRequest(baseReq, signer);

      // Capture headers BEFORE we send (the request is consumed by fetch)
      const headers: SignedHeaders = {
        signature: signed.headers.get('signature') ?? '(missing)',
        signatureInput: signed.headers.get('signature-input') ?? '(missing)',
        contentDigest: signed.headers.get('content-digest'),
      };
      setSignedHeaders(headers);

      // Forward the signed request. Note: theloopbreaker.com /api/agent/premium
      // serves CORS for these headers (Signature, Signature-Input, Content-Digest).
      const res = await fetch(signed);
      let json: any;
      try {
        json = await res.json();
      } catch {
        json = { rawText: await res.text() };
      }
      setResponse({ status: res.status, statusText: res.statusText, json });
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Sign-and-send failed');
    } finally {
      setBusy(false);
    }
  }

  async function handleSendUnsigned() {
    setBusy(true);
    setError(null);
    setSignedHeaders(null);
    setResponse(null);

    try {
      const body = JSON.stringify({ action: 'fetch_premium_unsigned', timestamp: Date.now() });
      setBodyText(body);

      const res = await fetch(PREMIUM_URL, {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body,
      });
      let json: any;
      try {
        json = await res.json();
      } catch {
        json = { rawText: await res.text() };
      }
      setResponse({ status: res.status, statusText: res.statusText, json });
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Unsigned fetch failed');
    } finally {
      setBusy(false);
    }
  }

  const keyid = address ? formatKeyId(VAULTFIRE_CHAIN_ID, address as Address) : '(connect wallet)';

  return (
    <main>
      <Header />

      <div className="mb-6">
        <Link href="/" className="text-sm text-muted hover:text-white transition-colors">
          ← Back
        </Link>
      </div>

      <h1 className="text-2xl font-bold mb-2">ERC-8128 Demo</h1>
      <p className="text-muted text-sm mb-6">
        Sign an HTTP request with your Ethereum wallet (RFC 9421 + EIP-191) and hit the
        live tier-gated{' '}
        <span className="font-mono text-xs">/api/agent/premium</span> endpoint.
        Gold tier or higher passes; everyone else is rejected.
      </p>

      {!isConnected && (
        <div className="card">
          <p className="text-sm text-muted">
            Connect your wallet to sign and send a request.
          </p>
        </div>
      )}

      {isConnected && (
        <>
          {/* Identity card */}
          <div className="card mb-4">
            <div className="label mb-2">Your keyid</div>
            <div className="font-mono text-xs break-all text-white">{keyid}</div>
            <div className="label mt-3 mb-1">Endpoint</div>
            <div className="font-mono text-xs break-all text-muted">{PREMIUM_URL}</div>
            <div className="label mt-3 mb-1">Required tier</div>
            <div className="text-sm text-white">Gold or higher</div>
          </div>

          {/* Action buttons */}
          <div className="grid grid-cols-1 gap-3 mb-4">
            <button
              onClick={handleSendSigned}
              disabled={busy}
              className="btn-primary w-full block text-center"
            >
              {busy ? 'Signing & sending…' : 'Sign request and send'}
            </button>
            <button
              onClick={handleSendUnsigned}
              disabled={busy}
              className="btn-secondary w-full block text-center"
            >
              {busy ? 'Sending…' : 'Send unsigned (should fail 401)'}
            </button>
          </div>

          {error && (
            <div className="card mb-4 border border-red-500/40">
              <div className="label mb-1">Error</div>
              <div className="text-sm text-red-300">{error}</div>
            </div>
          )}

          {/* Response — shown FIRST so the result is immediately visible after sending */}
          {response && (
            <div
              ref={responseRef}
              className={`card mb-4 ${
                response.status >= 200 && response.status < 300
                  ? 'border-2 border-green-500/60 bg-green-500/5'
                  : response.status === 401 || response.status === 403
                    ? 'border-2 border-yellow-500/60 bg-yellow-500/5'
                    : 'border-2 border-red-500/60 bg-red-500/5'
              }`}
            >
              <div className="flex items-center gap-2 mb-3">
                <span className="text-2xl">
                  {response.status >= 200 && response.status < 300 ? '✓' : response.status === 401 || response.status === 403 ? '✗' : '!'}
                </span>
                <div>
                  <div className="text-lg font-bold text-white">
                    {response.status >= 200 && response.status < 300
                      ? 'Verified — Premium access granted'
                      : response.status === 403
                        ? 'Insufficient tier'
                        : response.status === 401
                          ? 'Signature rejected'
                          : `Response ${response.status}`}
                  </div>
                  <div className="text-xs text-muted">
                    HTTP {response.status} {response.statusText}
                  </div>
                </div>
              </div>

              {/* Quick summary of what came back */}
              {response.json && response.status === 200 && response.json.streetCred && (
                <div className="grid grid-cols-2 gap-3 mb-3 text-xs">
                  <div>
                    <div className="label">Tier</div>
                    <div className="text-white font-bold text-base">{response.json.streetCred.tierName}</div>
                  </div>
                  <div>
                    <div className="label">Score</div>
                    <div className="text-white font-bold text-base">{response.json.streetCred.score} / 95</div>
                  </div>
                  <div>
                    <div className="label">Bond</div>
                    <div className="text-white">{response.json.streetCred.bondActive ? 'Active' : 'None'}</div>
                  </div>
                  <div>
                    <div className="label">Insurance</div>
                    <div className="text-white">{response.json.premium?.insuranceEligible ? 'Eligible' : 'Not eligible'}</div>
                  </div>
                </div>
              )}
              {response.json && response.status === 403 && response.json.required && (
                <div className="text-sm text-white mb-3">
                  Required <span className="font-bold">{response.json.required.tierName}</span>, you are{' '}
                  <span className="font-bold">{response.json.actual?.tierName ?? 'None'}</span>.
                </div>
              )}

              <details>
                <summary className="text-xs text-muted cursor-pointer hover:text-white">View raw JSON response</summary>
                <pre className="font-mono text-xs whitespace-pre-wrap break-all text-white mt-2">
                  {JSON.stringify(response.json, null, 2)}
                </pre>
              </details>
            </div>
          )}

          {/* Request body */}
          {bodyText && (
            <div className="card mb-4">
              <div className="label mb-2">Request body</div>
              <pre className="font-mono text-xs whitespace-pre-wrap break-all text-muted">
                {bodyText}
              </pre>
            </div>
          )}

          {/* Signed headers */}
          {signedHeaders && (
            <div className="card mb-4">
              <div className="label mb-2">Signed headers (RFC 9421)</div>
              <div className="space-y-3">
                <Field label="Signature-Input" value={signedHeaders.signatureInput} />
                <Field label="Signature" value={signedHeaders.signature} />
                {signedHeaders.contentDigest && (
                  <Field label="Content-Digest" value={signedHeaders.contentDigest} />
                )}
              </div>
            </div>
          )}

          {/* What's happening */}
          <div className="card mb-4">
            <div className="label mb-2">What this proves</div>
            <ul className="text-xs text-muted space-y-2 list-disc ml-4">
              <li>
                Your wallet signs an EIP-191 message over the canonical RFC 9421
                signature base — covers method, URL, headers, and body digest.
              </li>
              <li>
                The server recovers your address from the signature, looks up your
                live Street Cred score on-chain, and gates by tier.
              </li>
              <li>
                Tampering with the body changes the digest and verification fails.
                Replaying the same request fails too (60s nonce window).
              </li>
              <li>
                No bearer tokens, no API keys. Your wallet is the credential.
              </li>
            </ul>
          </div>

          <div className="card">
            <div className="label mb-2">Spec references</div>
            <ul className="text-xs space-y-1">
              <li>
                <a
                  href="https://ethereum-magicians.org/t/erc-8128-signed-http-requests-with-ethereum/"
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-white underline"
                >
                  ERC-8128 discussion
                </a>
              </li>
              <li>
                <a
                  href="https://datatracker.ietf.org/doc/rfc9421/"
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-white underline"
                >
                  RFC 9421 — HTTP Message Signatures
                </a>
              </li>
              <li>
                <a
                  href="https://github.com/slice-so/erc8128"
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-white underline"
                >
                  slice-so/erc8128 reference impl
                </a>
              </li>
            </ul>
          </div>
        </>
      )}
    </main>
  );
}

function Field({ label, value }: { label: string; value: string }) {
  return (
    <div>
      <div className="text-xs text-muted mb-1">{label}</div>
      <pre className="font-mono text-[10px] whitespace-pre-wrap break-all text-white">
        {value}
      </pre>
    </div>
  );
}
