import NextAuth, { AuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { JWT } from "next-auth/jwt";
import { Session } from "next-auth";
import { ROUTES } from "@/constants/routes";
import URLS from "@/redux/api/constants";
import { BaseQueryApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { isEnvFlagEnabled } from "@/lib/envFlags";
// import { usersPermissions } from "@/constants/permissions";

interface ExtendedToken extends JWT {
  accessToken?: string;
  refreshToken?: string;
  userId?: string;
  permissions?: string[];
  role?: string;
  companyId?: string;
  userType?: string;
  firstName?: string;
  lastName?: string;
  isMetaConnected?: boolean;
  accountAccessibleForMeta?: boolean;
}

interface ExtendedSession extends Session {
  accessToken?: string;
  refreshToken?: string;
  userId?: string;
  permissions?: string[];
  role?: string;
  companyId?: string;
  userType?: string;

  // User info
  firstName?: string;
  lastName?: string;
  fullName?: string;
  isMetaConnected?: boolean;
  accountAccessibleForMeta?: boolean;
}

const rawBaseQuery = fetchBaseQuery({
  baseUrl: URLS.HOST_URL,
});

export const authOptions: AuthOptions = {
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
        fcmToken: { label: "FcmToken", type: "fcmToken" },
      },
      async authorize(credentials) {
        if (!credentials) return null;

        const { fcmToken } = credentials;

        const result: any = await rawBaseQuery(
          {
            url: `${URLS.AUTH}/login`,
            method: "POST",
            body: {
              email: credentials.email,
              password: credentials.password,
            },
            credentials: "same-origin",
            headers: fcmToken ? { deviceToken: fcmToken } : undefined,
          },
          {
            signal: new AbortController().signal,
            abort: () => {},
            dispatch: () => {},
            getState: () => ({}),
            extra: undefined,
            endpoint: "",
            type: "query",
          } satisfies Partial<BaseQueryApi>,
          {},
        );
        if (result.error || !result.data?.success) return null;

        const { user, tokens, permissions, isMetaConnected } = result.data.data;
        const userType = user?.companyType;

      const accountAccessibleForMeta = isEnvFlagEnabled(
        "NEXT_PUBLIC_ALL_ACCOUNT_ACCESSIBLE_META",
      )
        ? true
        : credentials.email === process.env.NEXT_TEST_META_LEAD_EMAIL;

        return {
          ...user,
          accessToken: tokens.access.token,
          refreshToken: tokens.refresh.token,
          permissions,
          companyName: user.companyName ?? "",
          companyId: user.companyId ?? "",
          role: userType,
          firstName: user.firstName,
          lastName: user.lastName,

          fullName: user.firstName + " " + user.lastName,
          isMetaConnected,
          accountAccessibleForMeta,
        };
      },
    }),
  ],
  session: {
    strategy: "jwt",
  },
  callbacks: {
    async jwt({
      token,
      user,
      trigger,
      session,
    }: {
      token: ExtendedToken;
      user?: any;
      trigger?: string;
      session?: any;
    }): Promise<ExtendedToken> {
      if (trigger === "update" && session?.user) {
        if (session.user.firstName) {
          token.firstName = session.user.firstName;
        }
        if (session.user.lastName) {
          token.lastName = session.user.lastName;
        }
      }

      if (user) {
        token.accessToken = user.accessToken;
        token.refreshToken = user.refreshToken;
        token.userId = user.id;
        token.permissions = user.permissions || [];
        token.role = user.role;
        token.companyId = user.companyId;
        token.userType = user.userType;
        token.firstName = user.firstName;
        token.lastName = user.lastName;
        token.isMetaConnected = user.isMetaConnected;
        token.accountAccessibleForMeta = user.accountAccessibleForMeta;
      }
      return token;
    },
    async session({
      session,
      token,
    }: {
      session: ExtendedSession;
      token: ExtendedToken;
    }): Promise<ExtendedSession> {
      session.accessToken = token.accessToken;
      session.refreshToken = token.refreshToken;
      session.userId = token.userId;
      session.permissions = token.permissions || [];
      session.role = token.role;
      session.companyId = token.companyId;
      session.userType = token.userType;

      // User info
      session.firstName = token.firstName;
      session.lastName = token.lastName;
      session.fullName =
        token.firstName && token.lastName
          ? `${token.firstName} ${token.lastName}`
          : undefined;
      session.isMetaConnected = token.isMetaConnected;
      session.accountAccessibleForMeta = token.accountAccessibleForMeta;
      return session;
    },
  },
  pages: {
    signIn: ROUTES.LOGIN,
  },
  secret: process.env.NEXTAUTH_SECRET,
};

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
