import type { Context, CookieOptions } from "@wrnexus/core";
import { SecurityError } from "./errors.ts";

export interface SecureCookieOptions extends CookieOptions {
  hostOnly?: boolean;
}

export function secureCookieOptions(
  ctx: Pick<Context, "url">,
  options: SecureCookieOptions = {},
): CookieOptions {
  const secure = options.secure ?? ctx.url.protocol === "https:";
  const sameSite = options.sameSite ?? "Lax";
  if (sameSite.toString().toLowerCase() === "none" && !secure) {
    throw new SecurityError(
      "WRN-SEC-COOKIE-SAMESITE",
      "SameSite=None cookies must also use Secure.",
    );
  }
  if (options.hostOnly && options.domain) {
    throw new SecurityError("WRN-SEC-COOKIE-HOST", "Host-only cookies cannot set Domain.");
  }
  return {
    path: options.path ?? "/",
    ...options,
    domain: options.hostOnly ? undefined : options.domain,
    httpOnly: options.httpOnly ?? true,
    secure,
    sameSite,
  };
}

export function setSecureCookie(
  ctx: Pick<Context, "url" | "cookies">,
  name: string,
  value: string,
  options: SecureCookieOptions = {},
): void {
  if (name.startsWith("__Host-") && (options.domain || (options.path && options.path !== "/"))) {
    throw new SecurityError(
      "WRN-SEC-COOKIE-HOST-PREFIX",
      "__Host- cookies require Path=/ and must not set Domain.",
    );
  }
  ctx.cookies.set(
    name,
    value,
    secureCookieOptions(ctx, {
      ...options,
      hostOnly: name.startsWith("__Host-") || options.hostOnly,
      path: name.startsWith("__Host-") ? "/" : options.path,
      secure: name.startsWith("__Host-") ? true : options.secure,
    }),
  );
}
