/**
 * JWT utilities for Telegram bridge connections.
 *
 * When a user connects their Telegram chat to a mesh, the broker generates
 * a short-lived JWT containing mesh credentials. The Telegram bot decodes
 * this token to establish the connection.
 *
 * Pure-crypto implementation — no external JWT library.
 * Tokens are URL-safe (base64url) for use as Telegram deep link parameters.
 *
 * IMPORTANT: The JWT payload contains the member's secretKey.
 * Never log the token or its decoded payload.
 */

import { createHmac } from "node:crypto";

// --- Types ---

export interface TelegramConnectPayload {
  meshId: string;
  meshSlug: string;
  memberId: string;
  pubkey: string;
  secretKey: string;   // ed25519 secret key — sensitive
  createdBy: string;   // Dashboard userId or CLI memberId
}

interface JwtClaims extends TelegramConnectPayload {
  iss: string;
  sub: string;
  iat: number;
  exp: number;
}

// --- Helpers ---

function base64url(data: string): string {
  return Buffer.from(data).toString("base64url");
}

function base64urlDecode(str: string): string {
  return Buffer.from(str, "base64url").toString("utf-8");
}

function sign(input: string, secret: string): string {
  return createHmac("sha256", secret).update(input).digest("base64url");
}

// --- Public API ---

const JWT_HEADER = base64url(JSON.stringify({ alg: "HS256", typ: "JWT" }));
const TOKEN_TTL_SECONDS = 15 * 60; // 15 minutes

/**
 * Create a signed JWT containing Telegram connect credentials.
 * Expires in 15 minutes.
 */
export function generateTelegramConnectToken(
  payload: TelegramConnectPayload,
  secret: string,
): string {
  const now = Math.floor(Date.now() / 1000);

  const claims: JwtClaims = {
    ...payload,
    iss: "claudemesh-broker",
    sub: "telegram-connect",
    iat: now,
    exp: now + TOKEN_TTL_SECONDS,
  };

  const encodedPayload = base64url(JSON.stringify(claims));
  const signingInput = `${JWT_HEADER}.${encodedPayload}`;
  const signature = sign(signingInput, secret);

  return `${signingInput}.${signature}`;
}

/**
 * Validate and decode a Telegram connect JWT.
 * Returns the payload on success, or null on any failure
 * (bad signature, expired, wrong subject).
 */
export function validateTelegramConnectToken(
  token: string,
  secret: string,
): TelegramConnectPayload | null {
  try {
    const parts = token.split(".");
    if (parts.length !== 3) return null;

    const [headerB64, payloadB64, signatureB64] = parts as [string, string, string];

    // Verify signature
    const signingInput = `${headerB64}.${payloadB64}`;
    const expectedSignature = sign(signingInput, secret);
    // Constant-time comparison to prevent timing attacks
    const a = Buffer.from(signatureB64);
    const b = Buffer.from(expectedSignature);
    if (a.length !== b.length) return null;
    const { timingSafeEqual } = require("node:crypto");
    if (!timingSafeEqual(a, b)) return null;

    // Verify header algorithm
    const header = JSON.parse(base64urlDecode(headerB64)) as { alg?: string };
    if (header.alg !== "HS256") return null;

    // Decode and validate claims
    const claims = JSON.parse(base64urlDecode(payloadB64)) as JwtClaims;

    // Check subject
    if (claims.sub !== "telegram-connect") return null;

    // Check expiry
    const now = Math.floor(Date.now() / 1000);
    if (claims.exp < now) return null;

    // Check iat not in the future (30s tolerance)
    if (claims.iat > now + 30) return null;

    // Extract payload fields (strip JWT claims)
    const {
      meshId,
      meshSlug,
      memberId,
      pubkey,
      secretKey,
      createdBy,
    } = claims;

    // Basic presence check
    if (!meshId || !meshSlug || !memberId || !pubkey || !secretKey || !createdBy) {
      return null;
    }

    return { meshId, meshSlug, memberId, pubkey, secretKey, createdBy };
  } catch {
    return null;
  }
}

/**
 * Generate a Telegram deep link that passes the JWT as start parameter.
 * Format: https://t.me/{botUsername}?start={token}
 */
export function generateDeepLink(token: string, botUsername: string): string {
  return `https://t.me/${botUsername}?start=${token}`;
}
