import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import { Signup } from "../components/_layouts/_organisms/auth/Signup";
import { Login } from "../components/_layouts/_organisms/auth/Login";
import { DashBoard } from "./Dashboard";
import { Project } from "./Project";
import { ApiKey } from "./ApiKey";
import { CreateProject } from "../components/_layouts/CreateProject";
import { CreateApiKey } from "../components/_layouts/CreateApiKey";
import { CreateCompany } from "./CreateCompany";
import { Company } from "./Company";
import { AddCompanyMember } from "./AddCompanyMember";
import { ForgotPassword } from "../components/_layouts/_organisms/auth/ForgotPassword";
import { ForgotPasswordCallback } from "../components/_layouts/_organisms/auth/ForgotPasswordCallback";
import { Request } from "./Request";
import NotFound from "./NotFound";
import { CompleteOnboarding } from "../components/_layouts/CompleteOnboarding";
import { useContext, useEffect } from "react";
import * as AuthContext from "../contexts/AuthContext";
import { OperationResult, useMutation } from "urql";
import {
  RefreshTokenInput,
  RefreshTokenMutationDocument,
  RefreshTokenResponse,
} from "../gql-codegen/graphql";
import { AppStateContext } from "../contexts/AppContext";
import { Protected } from "../components/_layouts/Protected";

function AuthRedirect(props: React.PropsWithChildren<any>) {
  const auth = useContext(AuthContext.Context);

  const appState = useContext(AppStateContext);
  const [, refreshToken] = useMutation(RefreshTokenMutationDocument);

  useEffect(() => {
    let sessionValid = auth.checkJWTSession();

    if (sessionValid) {
      return;
    } else if (auth.refreshToken) {
      refreshToken({ refreshToken: auth.refreshToken } as RefreshTokenInput)
        .then(
          (result: OperationResult<{ refreshToken: RefreshTokenResponse }>) => {
            try {
              if (result.data?.refreshToken.success) {
                auth.setValue({
                  accessToken: result.data?.refreshToken.accessToken ?? "",
                  refreshToken: auth.refreshToken,
                });
                sessionValid = auth.checkJWTSession();
              }
            } catch (e) {
              console.error(e);
            }
          },
        )
        .then(() => {
          if (!sessionValid) {
            auth.setValue({
              accessToken: null,
              refreshToken: null,
            });
            appState.updateOpenSidebar(false);
          }
        });
    }
  }, []);

  return <>{props.children}</>;
}

export function Router() {
  return (
    <BrowserRouter>
      <Routes>
        <Route
          path="/login"
          element={
            <AuthRedirect>
              <Login />
            </AuthRedirect>
          }
        />
        <Route
          path="/signup"
          element={
            <AuthRedirect>
              <Signup />
            </AuthRedirect>
          }
        />
        <Route
          path="/forgot-password"
          element={
            <AuthRedirect>
              <ForgotPassword />
            </AuthRedirect>
          }
        />
        <Route
          path="/password-reset"
          element={
            <AuthRedirect>
              <ForgotPasswordCallback />
            </AuthRedirect>
          }
        />
        <Route
          path="/complete-onboarding"
          element={
            <Protected>
              <CompleteOnboarding />
            </Protected>
          }
        />
        <Route
          path="/complete-onboarding"
          element={
            <Protected>
              <Route index element={<Navigate to="/dashboard" />} />
            </Protected>
          }
        />
        <Route
          path="/dashboard"
          element={
            <Protected>
              <DashBoard />
            </Protected>
          }
        />
        <Route
          path="/"
          element={
            <Protected>
              <DashBoard />
            </Protected>
          }
        />
        <Route
          path="/company/:companyId/project/create"
          element={
            <Protected>
              <CreateProject />
            </Protected>
          }
        />
        <Route
          path="/api-keys/create"
          element={
            <Protected>
              <CreateApiKey />
            </Protected>
          }
        />
        <Route
          path="/company/create"
          element={
            <Protected>
              <CreateCompany />
            </Protected>
          }
        />
        <Route
          path="/company/:companyId"
          element={
            <Protected>
              <Company />
            </Protected>
          }
        />
        <Route
          path="/company/:companyId/add-member"
          element={
            <Protected>
              <AddCompanyMember />
            </Protected>
          }
        />
        <Route
          path="/company/:companyId/project/create"
          element={
            <Protected>
              <CreateProject />
            </Protected>
          }
        />
        <Route
          path="/company/:companyId/project/:projectId"
          element={
            <Protected>
              <Project />
            </Protected>
          }
        />
        <Route
          path="/company/:companyId/project/:projectId/api-key/create"
          element={
            <Protected>
              <CreateApiKey />
            </Protected>
          }
        />
        <Route
          path="/company/:companyId/project/:projectId/api-key/:apiKeyId"
          element={
            <Protected>
              <ApiKey />
            </Protected>
          }
        />
        <Route
          path="/company/:companyId/project/:projectId/api-key/:apiKeyId/request/:requestId"
          element={
            <Protected>
              <Request />
            </Protected>
          }
        />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}
