/**
 * TESC Client — Temporal Encrypted Secure Channel
 * Phase-Locked Authentication Tags (PLATs) for temporal message auth.
 * Per-message auth within 0.777s window, chained PLATs for tamper detection.
 *
 * @version 1.287.4
 * @license CC BY 4.0 — Zeq. H / Zeq 1.287 Hz Limited
 */
const TescClient = (() => {
  'use strict';

  const ZEQOND = 0.777;
  const HZ     = 1.287;
  const MAX_CHAIN = 5;

  let platChain = [];
  let sessionKey = null;

  // ── Generate PLAT (Phase-Locked Authentication Tag) ────────────────────
  async function generatePLAT(message, senderZid) {
    const now = Date.now() / 1000;
    const zeqond = Math.floor(now / ZEQOND);
    const phase = (now % ZEQOND) / ZEQOND;

    // Build the tag payload
    const payload = JSON.stringify({
      z: zeqond,
      p: phase.toFixed(6),
      m: await hashContent(message),
      s: senderZid,
      c: platChain.slice(-MAX_CHAIN),
      t: now,
    });

    // Hash the PLAT
    const platHash = await hashContent(payload);

    // Update chain
    platChain.push(platHash);
    if (platChain.length > MAX_CHAIN) platChain.shift();

    return {
      plat:    platHash,
      zeqond:  zeqond,
      phase:   phase,
      chain:   platChain.slice(),
      created: now,
    };
  }

  // ── Verify PLAT (check temporal validity) ──────────────────────────────
  function verifyPLAT(plat, maxAge = ZEQOND * 2) {
    if (!plat?.created) return { valid: false, reason: 'missing_timestamp' };

    const now = Date.now() / 1000;
    const age = now - plat.created;

    if (age > maxAge) return { valid: false, reason: 'expired', age };
    if (age < 0) return { valid: false, reason: 'future_timestamp', age };

    return { valid: true, age, withinZeqond: age <= ZEQOND };
  }

  // ── Attach PLAT headers to a fetch request ─────────────────────────────
  async function attachHeaders(headers, message, senderZid) {
    const plat = await generatePLAT(message, senderZid);
    headers['X-Zeq-PLAT']    = plat.plat;
    headers['X-Zeq-Zeqond']  = plat.zeqond.toString();
    headers['X-Zeq-Phase']   = plat.phase.toFixed(6);
    headers['X-Zeq-Chain']   = plat.chain.length.toString();
    return headers;
  }

  // ── SHA-256 hash helper ────────────────────────────────────────────────
  async function hashContent(content) {
    const data = new TextEncoder().encode(content);
    const hashBuffer = await crypto.subtle.digest('SHA-256', data);
    return Array.from(new Uint8Array(hashBuffer))
      .map(b => b.toString(16).padStart(2, '0'))
      .join('');
  }

  // ── Reset chain (on new session) ───────────────────────────────────────
  function reset() {
    platChain = [];
    sessionKey = null;
  }

  return { generatePLAT, verifyPLAT, attachHeaders, reset };
})();
