import crypto from "crypto";

/** Shared result-verification signing (used by the results API + verify endpoint). */

export interface VerifyPayload {
  i: number; // institutionId
  k: string; // exam key: `e:<examId>` or `a:<FORMAT>:<classId>:<sortedExamIds>`
  s: number; // studentId
  t: number; // total obtained
  g: string; // overall grade
}

/* Printable institutional reports (exam schedule, inventory, ...) sign the
   same way, with a report-shaped payload — the QR on each report encodes
   /verify/result?t=... so scanners can confirm it was issued by the school. */

export interface ReportVerifyPayload {
  i: number; // institutionId
  rt: "exam-schedule" | "inventory"; // report type
  k: string; // report key: examId or "all"
  ts: number; // issued at (epoch ms)
}

function secret() {
  return process.env.JWT_SECRET ?? "increlogems-dev-secret";
}

function b64url(input: Buffer | string) {
  return Buffer.from(input).toString("base64url");
}

function hmac(body: string): string {
  return crypto.createHmac("sha256", secret()).update(body).digest("base64url");
}

export function signResultToken(p: VerifyPayload): string {
  const body = b64url(JSON.stringify(p));
  return `${body}.${hmac(body)}`;
}

export function signReportToken(p: ReportVerifyPayload): string {
  const body = b64url(JSON.stringify(p));
  return `${body}.${hmac(body)}`;
}

export function verifyResultToken(
  token: string
): { ok: true; payload: VerifyPayload } | { ok: false } {
  const [body, sig] = token.split(".");
  if (!body || !sig) return { ok: false };
  const expected = crypto.createHmac("sha256", secret()).update(body).digest("base64url");
  const a = Buffer.from(sig);
  const b = Buffer.from(expected);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return { ok: false };
  try {
    const payload = JSON.parse(Buffer.from(body, "base64url").toString("utf8")) as VerifyPayload;
    if (typeof payload.i !== "number" || typeof payload.s !== "number") return { ok: false };
    return { ok: true, payload };
  } catch {
    return { ok: false };
  }
}

export function verifyReportToken(
  token: string
): { ok: true; payload: ReportVerifyPayload } | { ok: false } {
  const [body, sig] = token.split(".");
  if (!body || !sig) return { ok: false };
  const expected = hmac(body);
  const a = Buffer.from(sig);
  const b = Buffer.from(expected);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return { ok: false };
  try {
    const payload = JSON.parse(Buffer.from(body, "base64url").toString("utf8")) as ReportVerifyPayload;
    if (typeof payload.i !== "number" || (payload.rt !== "exam-schedule" && payload.rt !== "inventory")) {
      return { ok: false };
    }
    return { ok: true, payload };
  } catch {
    return { ok: false };
  }
}
