import { base64url } from "jose"

function generateVerifier(length: number): string {
  const buffer = new Uint8Array(length)
  crypto.getRandomValues(buffer)
  return base64url.encode(buffer)
}

async function generateChallenge(verifier: string, method: "S256" | "plain") {
  if (method === "plain") return verifier
  const encoder = new TextEncoder()
  const data = encoder.encode(verifier)
  const hash = await crypto.subtle.digest("SHA-256", data)
  return base64url.encode(new Uint8Array(hash))
}

export async function generatePKCE(length: number = 64) {
  if (length < 43 || length > 128) {
    throw new Error(
      "Code verifier length must be between 43 and 128 characters",
    )
  }
  const verifier = generateVerifier(length)
  const challenge = await generateChallenge(verifier, "S256")
  return {
    verifier,
    challenge,
    method: "S256",
  }
}

export async function validatePKCE(
  verifier: string,
  challenge: string,
  method: "S256" | "plain" = "S256",
) {
  const generatedChallenge = await generateChallenge(verifier, method)
  // timing safe equals?
  return generatedChallenge === challenge
}
