import { useAuth } from "@clerk/remix";
import { FullProjectDto } from "~/browser-client";
import { LoaderFunction, defer } from "@remix-run/node";
import { Await, useLoaderData, useNavigate } from "@remix-run/react";
import { Suspense, useEffect } from "react";
import { Theme, useTheme } from "remix-themes";
import { withAuth } from "~/auth/withAuth";
import { Routes } from "~/routes";
import { getActiveProject } from "~/services/activeProject.server";
import { clerkClient } from "~/services/clerk.server";

const getUserWithPublicMetadata = async (userId: string) => {
  const startTime = Date.now();
  const TIMEOUT = 10000;
  const DELAY = 250;

  while (Date.now() - startTime < TIMEOUT) {
    const user = await clerkClient.users.getUser(userId);
    if (!user) {
      throw new Error("User not found! " + userId);
    }

    const { personalProjectId, personalEnvId } = user?.publicMetadata || {};
    if (personalProjectId && personalEnvId) {
      return user;
    }

    await new Promise((resolve) => setTimeout(resolve, DELAY));
  }
  throw new Error("Timeout reached without finding project!");
};

type LoaderData = {
  user: any;
  allProjects: FullProjectDto[];
  activeProject?: string;
};
export const loader: LoaderFunction = withAuth(async ({ api, userId, request }) => {
  const activeProject = await getActiveProject(request);
  const allProjects = await api.project.projectControllerGetAllProjects();
  const userPromise = getUserWithPublicMetadata(userId);

  return defer<LoaderData>({ user: userPromise, allProjects, activeProject });
});

const LoadingLogo = () => {
  const [theme] = useTheme();
  const isDarkMode = theme === Theme.DARK;

  return (
    <div className="flex h-screen flex-col items-center justify-center gap-8">
      <img src={isDarkMode ? "/DarkModeLogo.svg" : "/LightModeLogo.svg"} alt={"Montelo Logo"} className={"w-48"} />
    </div>
  );
};

const redirectComponent = ({
  allProjects,
  activeProject,
  user,
  orgId,
}: LoaderData & {
  orgId: string | null | undefined;
}) => {
  const navigate = useNavigate();

  useEffect(() => {
    const { personalProjectId, personalEnvId, hasOnboarded } = user?.publicMetadata || {};
    let projectId = null,
      envId = null,
      redirectPath = Routes.app.project.env.dashboard;

    if (!orgId && personalProjectId && personalEnvId) {
      redirectPath = hasOnboarded ? Routes.app.project.env.dashboard : Routes.app.project.env.onboarding;
      projectId = personalProjectId as string;
      envId = personalEnvId as string;
    } else if (allProjects.length) {
      const activeProjectObj = activeProject ? allProjects.find((p) => p.id === activeProject) : null;
      if (activeProjectObj) {
        projectId = activeProjectObj.id;
        envId = activeProjectObj.environments[0].id;
      } else {
        const firstProject = allProjects[0];
        projectId = firstProject.id;
        envId = firstProject.environments[0].id;
      }
    }

    if (projectId && envId) {
      const path = redirectPath({ projectId, envId });
      navigate(path, { unstable_viewTransition: true });
    }
  }, [user]);

  return <LoadingLogo />;
};

export default function RootRoute() {
  const auth = useAuth();
  const { user, allProjects, activeProject } = useLoaderData<LoaderData>();

  return (
    <Suspense fallback={<LoadingLogo />}>
      <Await resolve={user}>
        {(user) =>
          redirectComponent({
            activeProject,
            allProjects,
            user,
            orgId: auth.orgId,
          })
        }
      </Await>
    </Suspense>
  );
}
