import axios from "axios";
import { AuthOptions } from "next-auth";
import { JWT } from "next-auth/jwt";
import CredentialsProvider from "next-auth/providers/credentials";
import { apiInstance } from "./apiConfig";
import { IRefresh, ITokens } from "../types/token-type";
import GoogleProvider from "next-auth/providers/google";

const refreshToken = async (token: JWT): Promise<JWT> => {
  const UTC = new Date();

  const data = {
    refresh: token.refresh_token,
  };

  const response = await apiInstance.post<IRefresh>(
    "/users/refresh/",
    data
  );

  const expirationTime = new Date(UTC.getTime() + 14 * 60000);
  expirationTime.setTime(
    expirationTime.getTime() +
      expirationTime.getTimezoneOffset() * 60 * 1000 * -1
  );

  return {
    ...token,
    access_token: response.data.access,
    expires_in: expirationTime,
  };
};

export const authConfig: AuthOptions = {
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: {
          label: "Email",
          type: "text",
          placeholder: "jsmith@example.com",
        },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials, req): Promise<any> {
        if (!credentials?.email || !credentials?.password)
          return null;

        const { email, password } = credentials;
        const data = {
          email,
          password,
        };

        const res = await apiInstance.post<ITokens>(
          "/users/login/",
          data
        );

        if ([200, 201].includes(res.status)) {
          const currentTime = new Date();
          const expirationTime = new Date(
            currentTime.getTime() + 14 * 60000
          );
          expirationTime.setTime(
            expirationTime.getTime() +
              expirationTime.getTimezoneOffset() * 60 * 1000 * -1
          );

          const user = {
            refresh_token: res.data.refresh_token,
            access_token: res.data.access_token,
            expires_in: expirationTime,
          };

          return user;
        }

        return null;
      },
    }),
    GoogleProvider({
      clientId: process.env.CLIENT_ID as string,
      clientSecret: process.env.CLIENT_SECRET as string,
    }),
  ],
  pages: {
    signIn: "/sign-in",
  },
  session: {
    strategy: "jwt",
  },
  callbacks: {
    async signIn({ account, user }) {
      if (account?.provider === "google") {
        const data = {
          auth_token: account?.id_token,
        };

        const res = await apiInstance.post<ITokens>(
          "/users/google/",
          data
        );

        if (![200, 201].includes(res.status)) {
          return false;
        }

        const currentTime = new Date();

        const expirationTime = new Date(
          currentTime.getTime() + 15 * 60000
        );

        user.access_token = res.data.access_token;
        user.refresh_token = res.data.refresh_token;
        user.expires_in = expirationTime;
      }

      return true;
    },
    async jwt({ token, user }) {
      if (user) return { ...token, ...user };

      const UTC = new Date();
      const currentTime = new Date(UTC.getTime());
      currentTime.setTime(
        currentTime.getTime() +
          currentTime.getTimezoneOffset() * 60 * 1000 * -1
      );

      const isValid =
        new Date(currentTime).getTime() <=
        new Date(token.expires_in).getTime();

      if (isValid) return token;

      return await refreshToken(token);
    },

    async session({ token, session }) {
      session.access_token = token.access_token;
      session.refresh_token = token.refresh_token;
      session.expires_in = token.expires_in;

      return session;
    },
  },
};
