import { createHmac, timingSafeEqual } from "crypto";
import type { BallotVerificationMethod } from "@/types";

const TOKEN_TTL_MS = 2 * 60 * 60 * 1000;

function secret(): string {
  return process.env.NEXTAUTH_SECRET ?? "surveystronghold-dev-only";
}

export interface VotingTokenPayload {
  electionId: string;
  voterRollId: string;
  verificationMethod: BallotVerificationMethod;
  exp: number;
}

export function signVotingToken(
  electionId: string,
  voterRollId: string,
  verificationMethod: BallotVerificationMethod = "email",
  ttlMs = TOKEN_TTL_MS
): string {
  const exp = Date.now() + ttlMs;
  const payload = `${electionId}.${voterRollId}.${verificationMethod}.${exp}`;
  const sig = createHmac("sha256", secret()).update(payload).digest("base64url");
  return `${payload}.${sig}`;
}

export function verifyVotingToken(token: string): VotingTokenPayload | null {
  const parts = token.split(".");
  // New format: electionId.voterRollId.method.exp.sig (5 parts)
  // Legacy format: electionId.voterRollId.exp.sig (4 parts) — treat as email
  if (parts.length === 4) {
    const [electionId, voterRollId, expRaw, sig] = parts;
    if (!electionId || !voterRollId || !expRaw || !sig) return null;
    const payload = `${electionId}.${voterRollId}.${expRaw}`;
    const expected = createHmac("sha256", secret())
      .update(payload)
      .digest("base64url");
    const sigBuf = Buffer.from(sig);
    const expectedBuf = Buffer.from(expected);
    if (sigBuf.length !== expectedBuf.length) return null;
    if (!timingSafeEqual(sigBuf, expectedBuf)) return null;
    const exp = Number(expRaw);
    if (!Number.isFinite(exp) || Date.now() > exp) return null;
    return { electionId, voterRollId, verificationMethod: "email", exp };
  }

  if (parts.length !== 5) return null;
  const [electionId, voterRollId, verificationMethod, expRaw, sig] = parts;
  if (!electionId || !voterRollId || !verificationMethod || !expRaw || !sig) {
    return null;
  }
  if (
    verificationMethod !== "email" &&
    verificationMethod !== "sms_2fa" &&
    verificationMethod !== "email_sms"
  ) {
    return null;
  }

  const payload = `${electionId}.${voterRollId}.${verificationMethod}.${expRaw}`;
  const expected = createHmac("sha256", secret())
    .update(payload)
    .digest("base64url");

  const sigBuf = Buffer.from(sig);
  const expectedBuf = Buffer.from(expected);
  if (sigBuf.length !== expectedBuf.length) return null;
  if (!timingSafeEqual(sigBuf, expectedBuf)) return null;

  const exp = Number(expRaw);
  if (!Number.isFinite(exp) || Date.now() > exp) return null;

  return { electionId, voterRollId, verificationMethod, exp };
}
