import { decodeBase64, encodeBase64, isBase64 } from "./bytes";

export const HTTP_METHODS = {
  "GET": {
    safe: true,
    idempotent: true,
  },
  "POST": {
    safe: false,
    idempotent: false,
  },
  "PUT": {
    safe: false,
    idempotent: true,
  },
  "DELETE": {
    safe: false,
    idempotent: true,
  },
  "PATCH": {
    safe: false,
    idempotent: false,
  },
  "OPTIONS": {
    safe: true,
    idempotent: true,
  },
  "HEAD": {
    safe: true,
    idempotent: true,
  },
  "TRACE": {
    safe: true,
    idempotent: true,
  },
  "CONNECT": {
    safe: false,
    idempotent: false,
  },
} as const;
export type HttpMethod = keyof typeof HTTP_METHODS;

export function decodeBasicAuthorizationHeader(value: string): [string, string] | null {
  const [type, encoded, ...rest] = value.split(' ');
  if (rest.length > 0) return null;
  if (!encoded) return null;
  if (type !== 'Basic') return null;
  if (!isBase64(encoded)) return null;
  const decoded = new TextDecoder().decode(decodeBase64(encoded));
  const split = decoded.split(':');
  return [split[0], split.slice(1).join(':')];
}
import.meta.vitest?.test("decodeBasicAuthorizationHeader", ({ expect }) => {
  // Test with valid Basic Authorization header
  const username = "user";
  const password = "pass";
  const encoded = encodeBasicAuthorizationHeader(username, password);
  expect(decodeBasicAuthorizationHeader(encoded)).toEqual([username, password]);

  // Test with password containing colons
  const complexPassword = "pass:with:colons";
  const encodedComplex = encodeBasicAuthorizationHeader(username, complexPassword);
  expect(decodeBasicAuthorizationHeader(encodedComplex)).toEqual([username, complexPassword]);

  // Test with invalid headers
  expect(decodeBasicAuthorizationHeader("NotBasic dXNlcjpwYXNz")).toBe(null); // Wrong type
  expect(decodeBasicAuthorizationHeader("Basic")).toBe(null); // Missing encoded part
  expect(decodeBasicAuthorizationHeader("Basic not-base64")).toBe(null); // Not base64
  expect(decodeBasicAuthorizationHeader("Basic dXNlcjpwYXNz extra")).toBe(null); // Extra parts
});

export function encodeBasicAuthorizationHeader(id: string, password: string): string {
  if (id.includes(':')) throw new Error("Basic authorization header id cannot contain ':'");
  return `Basic ${encodeBase64(new TextEncoder().encode(`${id}:${password}`))}`;
}
import.meta.vitest?.test("encodeBasicAuthorizationHeader", ({ expect }) => {
  // Test with simple username and password
  const encoded = encodeBasicAuthorizationHeader("user", "pass");
  expect(encoded).toMatch(/^Basic [A-Za-z0-9+/=]+$/); // Should start with "Basic " followed by base64

  // Test with empty password
  const encodedEmptyPass = encodeBasicAuthorizationHeader("user", "");
  expect(encodedEmptyPass).toMatch(/^Basic [A-Za-z0-9+/=]+$/);

  // Test with password containing special characters
  const encodedSpecialChars = encodeBasicAuthorizationHeader("user", "p@ss!w0rd");
  expect(encodedSpecialChars).toMatch(/^Basic [A-Za-z0-9+/=]+$/);

  // Test with username containing colon should throw
  expect(() => encodeBasicAuthorizationHeader("user:name", "pass")).toThrow();
});
