import { User } from "@clerk/remix/api.server";
import { getAuth } from "@clerk/remix/ssr.server";
import { Configuration } from "@montelo/browser-client";
import { LoaderFunction, json, redirect } from "@remix-run/node";
import { Outlet, unstable_useViewTransitionState, useLoaderData, useParams } from "@remix-run/react";
import { PanelRightClose } from "lucide-react";
import { useState } from "react";
import Stripe from "stripe";
import { Api } from "~/api";
import { PageBreadcrumb } from "~/components/nav/header/PageBreadcrumb";
import { Header } from "~/components/nav/sidebar/Header";
import { Sidebar } from "~/components/nav/sidebar/Sidebar";
import { env } from "~/config/environment.server";
import { Routes } from "~/routes";
import { clerkClient } from "~/services/clerk.server";
import { AppLayoutLoader } from "~/types/AppLayoutLoader.types";

export const loader: LoaderFunction = async (args) => {
  const auth = await getAuth(args);
  const token = await auth.getToken();
  const { userId, orgId } = auth;

  if (!token || !userId) {
    return redirect(Routes.auth.login);
  }

  const projectId = args.params.projectId!;

  const configuration = new Configuration({
    basePath: env.SERVER_BASE_URL,
    accessToken: token,
    headers: {
      connection: "keep-alive",
      "x-montelo-project-id": projectId || "",
    },
  });
  const api = new Api(configuration);
  const envId = args.params.envId!;

  const subscription = await api.payment.paymentControllerGetUserSubscription();

  // Create a Stripe customer session
  const stripe = new Stripe(env.STRIPE_SECRET_KEY);
  const customerSessionPromise = stripe.customerSessions.create({
    customer: subscription.stripeCustomerId,
    components: {
      pricing_table: {
        enabled: true,
      },
    },
  });

  const environmentPromise = api.environment.environmentControllerGetEnv({
    envId,
  });

  const projectPromise = api.project.projectControllerGetProject();
  const allProjectsForOrgPromise = api.organization.organizationControllerGetProjectsForOrg();

  const orgPromise = orgId
    ? clerkClient.organizations.getOrganization({ organizationId: orgId, slug: auth.orgSlug! })
    : undefined;
  const userPromise = clerkClient.users.getUser(userId);
  const orgMembershipsPromise = clerkClient.users.getOrganizationMembershipList({ userId });

  const [customerSession, environment, project, allProjects, org, user, orgMemberships] = await Promise.all([
    customerSessionPromise,
    environmentPromise,
    projectPromise,
    allProjectsForOrgPromise,
    orgPromise,
    userPromise,
    orgMembershipsPromise,
  ]);

  return json<AppLayoutLoader>({
    environment,
    project,
    allProjects,
    org,
    user,
    orgMemberships,
    subscription,
    customerSession,
    pricingTableId: env.STRIPE_PRICING_TABLE_ID,
    stripePublishableKey: env.STRIPE_PUBLISHABLE_KEY,
  });
};

export default function DashboardLayout() {
  const [isSidebarOpen, setIsSidebarOpen] = useState(true);
  const { project, allProjects, environment, org, user, orgMemberships } = useLoaderData<AppLayoutLoader>();

  const { projectId, envId } = useParams();
  const to = `/app/project/${projectId}/env/${envId}/dashboard`;
  const isViewTransition = unstable_useViewTransitionState(to);

  return (
    <div className={`${isViewTransition ? "transition-opacity duration-1000 ease-in-out" : ""}`}>
      <div className="flex h-full gap-5">
        <div
          className={`fixed bottom-0 overflow-hidden transition-all ${isSidebarOpen ? "left-0" : "left-[-220px]"} top-0 box-border flex w-[220px] flex-col gap-4 rounded border-r-2 px-2 pt-2`}
        >
          <Header orgMemberships={orgMemberships} org={org} closeSidebar={() => setIsSidebarOpen(false)} />
          <Sidebar project={project} user={user as User} />
        </div>

        <main className={`${isSidebarOpen ? "ml-[230px]" : ""} flex flex-1 flex-col transition-all`}>
          <div className="flex gap-2">
            {!isSidebarOpen && (
              <button className="opacity-40 hover:opacity-70" onClick={() => setIsSidebarOpen(true)}>
                <PanelRightClose size={18} />
              </button>
            )}
            <PageBreadcrumb project={project} allProjects={allProjects} environment={environment} />
          </div>
          <Outlet />
        </main>
      </div>
    </div>
  );
}
