import { cookies, headers } from "next/headers";
import { redirect } from "next/navigation";
import {
  buildMailEntryUrl,
  getMailAbsoluteUrl,
  getMailAppUrl,
  isLocalOrigin,
  resolveMailAppUrlFromHeaders,
  resolveOriginFromHeaders,
} from "@/lib/mail-urls";
import { getSessionSnapshotByEmail } from "@/lib/official-mail";

const SESSION_COOKIE = "official_mail_session";
const USER_COOKIE = "official_mail_user";

export type SessionUser = {
  email: string;
  companyName: string;
  displayName: string;
  mailConfigured: boolean;
  domain: string;
  mailbox: string;
};

async function resolveCookieDomain() {
  const requestHeaders = await headers();
  const currentOrigin = resolveOriginFromHeaders(requestHeaders, getMailAppUrl());

  if (isLocalOrigin(currentOrigin)) {
    return undefined;
  }

  const appUrl = process.env.NEXT_PUBLIC_APP_URL;

  if (!appUrl) {
    return undefined;
  }

  try {
    const hostname = new URL(appUrl).hostname;

    if (hostname === "localhost" || /^\d{1,3}(\.\d{1,3}){3}$/.test(hostname)) {
      return undefined;
    }

    return hostname.startsWith(".") ? hostname : `.${hostname}`;
  } catch {
    return undefined;
  }
}

function encodeUser(user: SessionUser) {
  return Buffer.from(JSON.stringify(user)).toString("base64url");
}

function decodeUser(value: string) {
  try {
    const decoded = Buffer.from(value, "base64url").toString("utf-8");
    return JSON.parse(decoded) as SessionUser;
  } catch {
    return null;
  }
}

export async function getSessionUser() {
  const cookieStore = await cookies();
  const session = cookieStore.get(SESSION_COOKIE)?.value;
  const user = cookieStore.get(USER_COOKIE)?.value;

  if (session !== "active" || !user) {
    return null;
  }

  const decodedUser = decodeUser(user);

  if (!decodedUser) {
    return null;
  }

  const snapshot = await getSessionSnapshotByEmail(decodedUser.email);
  return snapshot ?? decodedUser;
}

export async function requireSessionUser() {
  const user = await getSessionUser();

  if (!user) {
    redirect("/login");
  }

  return user;
}

export async function saveSessionUser(user: SessionUser) {
  const cookieStore = await cookies();
  const expires = new Date(Date.now() + 1000 * 60 * 60 * 8);
  const domain = await resolveCookieDomain();

  cookieStore.set(SESSION_COOKIE, "active", {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    expires,
    domain,
  });
  cookieStore.set(USER_COOKIE, encodeUser(user), {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    expires,
    domain,
  });
}

export async function clearSession() {
  const cookieStore = await cookies();
  const domain = await resolveCookieDomain();

  cookieStore.delete({ name: SESSION_COOKIE, path: "/", domain });
  cookieStore.delete({ name: USER_COOKIE, path: "/", domain });
}

export function getMailEntryUrl(
  user?: Pick<SessionUser, "mailConfigured"> | null,
) {
  return buildMailEntryUrl(user);
}

export async function getMailEntryUrlForCurrentRequest(
  user?: Pick<SessionUser, "mailConfigured"> | null,
) {
  const requestHeaders = await headers();
  return buildMailEntryUrl(user, resolveMailAppUrlFromHeaders(requestHeaders));
}

export async function getMailAuthUrlForCurrentRequest(path: string) {
  const requestHeaders = await headers();
  const baseUrl = resolveMailAppUrlFromHeaders(requestHeaders);
  return getMailAbsoluteUrl(path, baseUrl);
}

export async function redirectToCanonicalMailAuthHostIfNeeded(
  pathname: string,
  search = "",
) {
  const requestHeaders = await headers();
  const currentOrigin = resolveOriginFromHeaders(requestHeaders);
  const canonicalMailUrl = getMailAppUrl();

  if (currentOrigin === canonicalMailUrl) {
    return;
  }

  if (resolveMailAppUrlFromHeaders(requestHeaders) === currentOrigin) {
    return;
  }

  redirect(getMailAbsoluteUrl(`${pathname}${search}`, canonicalMailUrl));
}
