// ARC Proofing — live "ARC Proof It" demo.
// The SHA-256 is REAL (Web Crypto). Ed25519 signature + Bitcoin block are
// plausible stand-ins for the three-tier anchoring pipeline.
const { useState, useRef, useCallback } = React;

function randHex(n) {
  const c = '0123456789abcdef';
  let s = '';
  for (let i = 0; i < n; i++) s += c[(Math.random() * 16) | 0];
  return s;
}

async function sha256Hex(buf) {
  const digest = await crypto.subtle.digest('SHA-256', buf);
  return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');
}

function HashView({ hash }) {
  // group into 8-char segments, alternate shading for legibility
  const segs = hash.match(/.{1,8}/g) || [];
  return (
    <div className="hv">
      {segs.map((s, i) => (
        <span key={i} className={i % 2 ? 'seg' : ''}>{s}{i < segs.length - 1 ? ' ' : ''}</span>
      ))}
    </div>
  );
}

const TIER_DEFS = [
  { name: 'Ed25519 device signature', metaIdle: 'Instant — signs the hash on-device', },
  { name: 'OpenTimestamps attestation', metaIdle: 'Submitted to calendar servers', },
  { name: 'Bitcoin blockchain anchor', metaIdle: 'OP_RETURN commitment, 6-block confirmation', },
];

function ProofDemo() {
  const [text, setText] = useState('');
  const [running, setRunning] = useState(false);
  const [hash, setHash] = useState('');
  const [source, setSource] = useState('');           // label of what was hashed
  const [tiers, setTiers] = useState([
    { state: 'idle', meta: TIER_DEFS[0].metaIdle },
    { state: 'idle', meta: TIER_DEFS[1].metaIdle },
    { state: 'idle', meta: TIER_DEFS[2].metaIdle },
  ]);
  const [receipt, setReceipt] = useState(null);
  const [dragging, setDragging] = useState(false);
  const fileRef = useRef(null);

  const setTier = (i, patch) =>
    setTiers((prev) => prev.map((t, j) => (j === i ? { ...t, ...patch } : t)));

  const wait = (ms) => new Promise((r) => setTimeout(r, ms));

  const run = useCallback(async (buf, label) => {
    if (running) return;
    setRunning(true);
    setReceipt(null);
    setTiers([
      { state: 'idle', meta: TIER_DEFS[0].metaIdle },
      { state: 'idle', meta: TIER_DEFS[1].metaIdle },
      { state: 'idle', meta: TIER_DEFS[2].metaIdle },
    ]);

    const h = await sha256Hex(buf);
    setHash('');
    setSource(label);
    // reveal hash with a brief settle
    await wait(160);
    setHash(h);
    await wait(520);

    // Tier 1 — Ed25519
    setTier(0, { state: 'run', meta: 'Signing on-device…' });
    await wait(900);
    const sig = randHex(128);
    setTier(0, { state: 'done', meta: 'sig ' + sig.slice(0, 24) + '…' });

    // Tier 2 — OpenTimestamps
    setTier(1, { state: 'run', meta: 'Awaiting calendar attestation…' });
    await wait(1400);
    setTier(1, { state: 'done', meta: 'Pending attestation aggregated — proof saved' });

    // Tier 3 — Bitcoin
    setTier(2, { state: 'run', meta: 'Broadcasting OP_RETURN…' });
    await wait(900);
    const startBlock = 902000 + ((Math.random() * 4000) | 0);
    for (let c = 1; c <= 6; c++) {
      setTier(2, { state: 'run', meta: 'Confirmation ' + c + ' / 6 · block ' + (startBlock + c - 1) });
      await wait(360);
    }
    const block = startBlock + 5;
    setTier(2, { state: 'done', meta: 'Confirmed · block ' + block });

    await wait(200);
    setReceipt({
      id: 'arc_' + randHex(20),
      hash: h,
      ts: new Date().toISOString().replace('T', ' ').slice(0, 19) + 'Z',
      sig,
      block,
      source: label,
    });
    setRunning(false);
  }, [running]);

  const onProofText = () => {
    const v = text.trim() || 'A Record of Certainty — arcproof.ing';
    run(new TextEncoder().encode(v), v.length > 42 ? v.slice(0, 42) + '…' : v);
  };

  const onFile = (file) => {
    if (!file) return;
    file.arrayBuffer().then((buf) =>
      run(buf, file.name + ' · ' + (file.size > 1024 ? (file.size / 1024).toFixed(1) + ' KB' : file.size + ' B'))
    );
  };

  return (
    <div
      className={'demo' + (dragging ? ' dropping' : '')}
      onDragOver={(e) => { e.preventDefault(); setDragging(true); }}
      onDragLeave={() => setDragging(false)}
      onDrop={(e) => { e.preventDefault(); setDragging(false); onFile(e.dataTransfer.files[0]); }}
    >
      <div className="demo-head">
        <span className="lbl">ARC Proof It</span>
        <span className="live"><span className="dot" />SHA-256 runs in your browser</span>
      </div>
      <div className="demo-body">
        <div className="demo-input-row">
          <input
            className="demo-field mono"
            placeholder="Type anything, or drop a file…"
            value={text}
            onChange={(e) => setText(e.target.value)}
            onKeyDown={(e) => { if (e.key === 'Enter') onProofText(); }}
            disabled={running}
          />
          <button className="demo-go" onClick={onProofText} disabled={running}>
            {running ? 'Proofing…' : 'Proof It'}
          </button>
        </div>
        <p className="demo-hint">
          Nothing leaves your machine — only the hash is anchored.{' '}
          <span className="drop" onClick={() => fileRef.current && fileRef.current.click()}>Choose a file</span> instead.
          <input ref={fileRef} type="file" style={{ display: 'none' }} onChange={(e) => onFile(e.target.files[0])} />
        </p>

        {hash && (
          <div className="demo-hash">
            <p className="k">SHA-256 · {source}</p>
            <HashView hash={hash} />
          </div>
        )}

        {hash && (
          <div className="tiers">
            {TIER_DEFS.map((d, i) => (
              <div key={i} className={'tier' + (tiers[i].state === 'run' ? ' active' : '')}>
                <span className="tnum">T{i + 1}</span>
                <div className="tmid">
                  <div className="tname">{d.name}</div>
                  <div className="tmeta">{tiers[i].meta}</div>
                </div>
                <span className={'tstat ' + tiers[i].state}>
                  {tiers[i].state === 'idle' && 'Queued'}
                  {tiers[i].state === 'run' && <span><span className="spin">◜</span> Working</span>}
                  {tiers[i].state === 'done' && '✓ Anchored'}
                </span>
              </div>
            ))}
          </div>
        )}

        {receipt && (
          <div className={'receipt' + (receipt ? ' show' : '')}>
            <div className="rhead">
              <span className="rtitle">ARC Proof — receipt</span>
              <span className="rverified">Verified</span>
            </div>
            <div className="rgrid">
              <span className="rk">proof_id</span><span className="rv">{receipt.id}</span>
              <span className="rk">sha256</span><span className="rv">{receipt.hash}</span>
              <span className="rk">timestamp</span><span className="rv">{receipt.ts}</span>
              <span className="rk">ed25519</span><span className="rv">{receipt.sig.slice(0, 48)}…</span>
              <span className="rk">btc_block</span><span className="rv">#{receipt.block}</span>
              <span className="rk">verify_at</span><span className="rv">verify.arcproof.ing/{receipt.id}</span>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

window.ProofDemo = ProofDemo;
