import storeConfig from "discovery.config";

import { AUT_COOKIE_KEY } from "./constants";

import type { LoaderData } from "../types/LoaderData";

export interface ParsedCookie {
  sub: string;
  account: string;
  audience: string;
  sess: string;
  exp: number;
  type: string;
  userId: string;
  iat: number;
  customerId: string;
  isRepresentative: boolean;
  iss: string;
  jti: string;
}

type ExpireCookieClientParams = {
  name: string;
  path: string;
  domain?: string;
  secure?: boolean;
};

export function getAuthCookie(data: LoaderData) {
  const authCookie =
    data?.req?.cookies[`${AUT_COOKIE_KEY}_${storeConfig?.api.storeId}`] ?? "";

  return authCookie;
}

const valuesToRemove = ["vtex_session"];

export function getCookieWithoutSessionObjects(cookie: string) {
  const mappedCookie: Record<string, string> = Object.fromEntries(
    cookie.split(";").map((pair) => pair.split("="))
  );

  const newCookie: Record<string, string> = {};

  for (const key in mappedCookie) {
    if (!valuesToRemove.includes(key.toLocaleLowerCase())) {
      newCookie[key] = mappedCookie[key];
    }
  }

  return { Cookie: getCookieAsString(newCookie) };
}

export function getAuthFromCookie(cookie: string) {
  const mappedCookie: Record<string, string> = Object.fromEntries(
    cookie.split(";").map((pair) => pair.split("="))
  );

  const authCookie = {} as Record<string, string>;

  authCookie[`${AUT_COOKIE_KEY}_${storeConfig?.api.storeId}`] =
    mappedCookie[`${AUT_COOKIE_KEY}_${storeConfig?.api.storeId}`];

  return authCookie;
}

export function getParsedJWT(data: LoaderData): ParsedCookie | "" {
  const authCookie = getAuthCookie(data);

  if (!authCookie || authCookie === "") {
    return "";
  }

  return parseJwt(authCookie);
}

export function getCustomerIdFromCookieServerSide(data: LoaderData): string {
  const parsedCookie = getParsedJWT(data);

  return parsedCookie ? String(parsedCookie.customerId) : "";
}

export function getUserIdFromCookieServerSide(data: LoaderData): string {
  const parsedCookie = getParsedJWT(data);

  return parsedCookie ? String(parsedCookie.userId) : "";
}

export function getCookieAsString(cookie: Record<string, string>): string {
  let cookieString = "";
  Object.keys(cookie).forEach((cookieKey) => {
    cookieString += `${cookieKey}=${encodeURIComponent(cookie[cookieKey])};`;
  });

  return cookieString.slice(0, cookieString.length - 1);
}

function parseJwt(token: string): ParsedCookie {
  return JSON.parse(Buffer.from(token.split(".")[1], "base64").toString());
}

export const getVtexCookieNames = (cookieNames: string[]): string[] => {
  return cookieNames.filter((name) => name.toLowerCase().includes("vtex"));
};

export const getCookiePaths = (pathname: string): string[] => {
  const paths: string[] = ["/"];
  const pathParts = pathname.split("/").filter(Boolean);

  let current = "";
  for (const part of pathParts) {
    current += `/${part}`;
    if (!paths.includes(current)) paths.push(current);
  }

  return paths;
};

export const getCookieDomains = (
  hostname: string
): Array<string | undefined> => [
  undefined, // host-only cookie
  hostname,
  hostname.startsWith(".") ? hostname : `.${hostname}`,
];

export const expireCookieClient = ({
  name,
  path,
  domain,
  secure = false,
}: ExpireCookieClientParams): void => {
  const domainAttr = domain ? `; domain=${domain}` : "";
  const secureAttr = secure ? "; secure" : "";
  document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; max-age=0; path=${path}${domainAttr}; samesite=lax${secureAttr}`;
};
