import {
  createMiddleware,
  createServerFn,
  createServerOnlyFn,
} from "@tanstack/react-start";
import { getRequest } from "@tanstack/react-start/server";
import { Logger } from "@/lib/logger";
import z from "zod";

const logger = new Logger("Middleware");

export const PUBLIC_ROUTES = ["/login", "/logout", "/refresh-session"];

export const getSessionContext = createServerOnlyFn(
  async (request: Request, options?: { isServerFunction?: boolean }) => {
    const { getSessionContextCore } = await import("./supertokens-core.server");
    return getSessionContextCore(request, options);
  }
);

export const superTokensRequestMiddleware = createMiddleware({
  type: "request",
}).server(async ({ next, request }) => {
  const context = await getSessionContext(request);
  return next({ context });
});

export const superTokensFunctionMiddleware = createMiddleware({
  type: "function",
}).server(async ({ next }) => {
  const request = getRequest();

  try {
    const context = await getSessionContext(request, { isServerFunction: true });
    return next({ context });
  } catch (error: any) {
    if (error.message === "SESSION_REFRESH_REQUIRED") {
      throw new Response(
        JSON.stringify({
          error: "SESSION_REFRESH_REQUIRED",
          message: "Session needs to be refreshed"
        }),
        {
          status: 401,
          headers: { "Content-Type": "application/json" }
        }
      );
    }
    throw error;
  }
});

export const superTokensAdminFunctionMiddleware = createMiddleware({
  type: "function",
}).server(async ({ next }) => {
  const request = getRequest();

  try {
    const context = await getSessionContext(request, { isServerFunction: true });

    if (context.roles?.includes("Admin")) {
      return next({ context });
    }

    logger.error("Unauthorized user in admin function.", context);
    throw new Error("Unauthorized");
  } catch (error: any) {
    if (error.message === "SESSION_REFRESH_REQUIRED") {
      throw new Response(
        JSON.stringify({
          error: "SESSION_REFRESH_REQUIRED",
          message: "Session needs to be refreshed"
        }),
        {
          status: 401,
          headers: { "Content-Type": "application/json" }
        }
      );
    }
    throw error;
  }
});

export const setUserMetadata = createServerFn({ method: "POST" })
  .validator(
    z
      .object({
        first_name: z
          .string()
          .min(2)
          .max(20)
          .regex(
            /^[a-zA-Z0-9\s]+$/,
            "First name must be 2-20 characters long and contain only letters and spaces"
          ),
        last_name: z
          .string()
          .min(2)
          .max(20)
          .regex(
            /^[a-zA-Z0-9\s]+$/,
            "Last name must be 2-20 characters long and contain only letters and spaces"
          ),
        player_id: z.string(),
      })
      .partial()
  )
  .middleware([superTokensFunctionMiddleware])
  .handler(async ({ context, data }) => {
    const { userAuthId, metadata } = context;
    if (!userAuthId) return;

    const { updateUserMetadataFields } = await import(
      "./supertokens-core.server"
    );

    await updateUserMetadataFields(userAuthId, {
      first_name: data.first_name,
      last_name: data.last_name,
      player_id: data.player_id,
    });

    return {
      metadata: {
        ...metadata,
        ...data,
      },
    };
  });
