import { isLoggedInCookie } from "@/utils/createCookie";
import { Box, Container, Flex, Text, Title } from "@mantine/core";
import { redirect, type LoaderFunctionArgs } from "react-router";
import AuthLogo from "./(widgets)/authLogo";
import { ssoSignin } from "@/lib/features/auth/action";

/**
 * Landing point for the one-time sign-in links sent in console emails.
 *
 * The link carries a single-use token; this route trades it for a real session and
 * forwards the reader to the page the email was about. Everything happens in the
 * loader so the token is redeemed once, server-side, before anything renders — a
 * client-side exchange would burn the token again on every remount.
 *
 * Sits at `/sso` rather than under `/auth` on purpose: the root layout bounces
 * `/auth/*` to the dashboard for anyone who already has a session, which would
 * throw away the `next` target this link exists to deliver.
 */

export function meta() {
  return [{ title: "Signing you in — Admin Console" }];
}

const DEFAULT_NEXT = "/admin/dashboard";

/**
 * Only in-console destinations are honoured.
 *
 * `next` arrives in a URL that reaches people by email, which is exactly the shape
 * an open redirect is phished through. Anything that isn't a plain `/admin` path —
 * an absolute URL, a protocol-relative `//host`, a path outside the console — is
 * replaced with the dashboard rather than followed.
 */
function safeNext(raw: string | null): string {
  if (!raw) return DEFAULT_NEXT;
  if (!raw.startsWith("/admin") || raw.startsWith("//")) return DEFAULT_NEXT;
  return raw;
}

export async function loader({ request }: LoaderFunctionArgs) {
  const url = new URL(request.url);
  const token = url.searchParams.get("token");
  const next = safeNext(url.searchParams.get("next"));

  if (!token) {
    return redirect(`/auth/signin?sso=invalid&next=${encodeURIComponent(next)}`);
  }

  const response = await ssoSignin(token, request);
  const setCookieHeaders = response?.headers?.getSetCookie?.() ?? [];

  /*
   * A missing Set-Cookie means the token was expired, already used, or belongs to
   * a deactivated account. The distinction isn't surfaced: whoever clicked can just
   * sign in normally, and spelling out which of those it was tells an unauthorised
   * clicker something about the account.
   */
  if (!response?.ok || setCookieHeaders.length === 0) {
    return redirect(`/auth/signin?sso=expired&next=${encodeURIComponent(next)}`);
  }

  const headers = new Headers();
  setCookieHeaders.forEach((cookie) => headers.append("Set-Cookie", cookie));
  headers.append("Set-Cookie", await isLoggedInCookie.serialize("true"));

  return redirect(next, { headers });
}

/**
 * Only reached if the redirect above somehow doesn't take — the loader either
 * lands the reader on `next` or on the sign-in page.
 */
export default function ConsoleSso() {
  return (
    <Container fluid h="100vh">
      <Flex h="100%" w="100%" justify="center" align="center" direction="column">
        <Box w={400} maw="100%">
          <AuthLogo />
        </Box>
        <Box w={400} maw="100%" ta="center">
          <Title order={4}>Signing you in…</Title>
          <Text size="sm" c="dimmed" mt="sm">
            One moment while we open the console.
          </Text>
        </Box>
      </Flex>
    </Container>
  );
}
