import dayjs from 'dayjs';
import NextAuth, { NextAuthOptions, User } from 'next-auth';
import { JWT } from 'next-auth/jwt';
import GoogleProvider from 'next-auth/providers/google';

import { login } from '../../../api';
import { ROUTES } from '../../../routes';
import { WithJWT } from '../../../types/dto/user';

import { AUTH_EXPIRE_TIME } from './../../../../server/config/authentication';

const providers: NextAuthOptions['providers'] = [
  GoogleProvider({
    clientId: process.env.GOOGLE_CLIENT_ID as string,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
  }),
];

const callbacks: NextAuthOptions['callbacks'] = {};

callbacks.signIn = async function (params) {
  const { user, account } = params;
  if (account.provider === 'google') {
    const { id_token } = account;
    if (id_token) {
      const jwt = await login({
        googleOAuth: {
          idToken: id_token,
        },
      });
      if (jwt && jwt.access_token) {
        user.jwt = jwt;
        return true;
      }
    }
    return false;
  }

  return false;
};

type WithUser<T> = {
  // user.jwt = jwt;
  user: WithJWT<User>;
} & T;

callbacks.jwt = async function jwt(params) {
  const user = params.user as WithJWT<User>;
  if (user) {
    const tokenWithUser: WithUser<JWT> = {
      accessToken: user.accessToken,
      user,
    };
    return tokenWithUser;
  }

  return params.token;
};

callbacks.session = async function session(params) {
  const { session } = params;
  const tokenWithUser = params.token as WithUser<JWT>;
  session.user = tokenWithUser.user;
  return session;
};

callbacks.redirect = async function (params) {
  if (params.url.includes('/error')) return Promise.resolve('/');
  return Promise.resolve(params.url);
};

const options: NextAuthOptions = {
  providers,
  callbacks,
  pages: {
    error: ROUTES.AUTH_ERROR.href.pathname,
  },
  jwt: {
    maxAge: AUTH_EXPIRE_TIME,
  },
};

export default NextAuth(options);
