import { SignJWT, jwtVerify, type JWTPayload } from "jose";
import { randomUUID } from "crypto";

const ALGORITHM = "HS256";
const PURPOSE = "rebreak.cooldown";

function getSecret(): Uint8Array {
  const raw =
    process.env.REBREAK_COOLDOWN_SECRET ||
    process.env.NUXT_AUTH_SECRET ||
    // Last-resort fallback — deterministic within a single process lifetime.
    // A proper secret MUST be set via Infisical in production.
    "rebreak-cooldown-insecure-fallback-replace-me";
  return new TextEncoder().encode(raw);
}

export interface CooldownTokenPayload {
  userId: string;
  jti: string;
  cooldownEndsAt: string; // ISO-8601
}

/**
 * Signs a short-lived JWT that the iOS app can present to prove it has
 * permission to disable the DNS protection (cooldown expired on the server).
 *
 * Lifetime: 5 minutes — short enough to prevent replay attacks.
 * The `jti` ties the token to the exact CooldownRequest row.
 */
export async function signCooldownToken(
  userId: string,
  jti: string,
  cooldownEndsAt: Date,
): Promise<string> {
  const secret = getSecret();
  const now = Math.floor(Date.now() / 1000);

  return new SignJWT({
    sub: userId,
    jti,
    purpose: PURPOSE,
    cooldown_ends_at: cooldownEndsAt.toISOString(),
  } satisfies JWTPayload & { purpose: string; cooldown_ends_at: string })
    .setProtectedHeader({ alg: ALGORITHM })
    .setIssuedAt(now)
    .setExpirationTime(now + 5 * 60) // 5 minutes
    .sign(secret);
}

/**
 * Verifies the token and returns its payload or null if invalid/expired.
 */
export async function verifyCooldownToken(
  token: string,
): Promise<CooldownTokenPayload | null> {
  try {
    const { payload } = await jwtVerify(token, getSecret(), {
      algorithms: [ALGORITHM],
    });

    if (
      typeof payload.sub !== "string" ||
      typeof payload.jti !== "string" ||
      payload.purpose !== PURPOSE ||
      typeof payload.cooldown_ends_at !== "string"
    ) {
      return null;
    }

    return {
      userId: payload.sub,
      jti: payload.jti,
      cooldownEndsAt: payload.cooldown_ends_at,
    };
  } catch {
    return null;
  }
}

/** Convenience: generate a new JTI (UUID v4). */
export function generateJti(): string {
  return randomUUID();
}
