import { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import crypto from "crypto";
import db from "@/lib/db";
import bcrypt from "bcrypt";
// import { mockSession } from "next-auth/client/__tests__/helpers/mocks";
import {getLogger} from "@/utils/logger";

const logger = getLogger("api/auth/auth-options");

// import user = mockSession.user;


function generateSessionState(): string | undefined {
  return crypto.randomUUID().toString();
}

export const authOptions: NextAuthOptions = {
  // Configure one or more authentication providers
  pages: {
    signIn: "/login",
    signOut: "/?callbackUrl=/",
    error: "/login",
    newUser: "/",
  },
  secret: process.env.NEXTAUTH_SECRET,
  session: {
    strategy: "jwt",
    maxAge: 24 * 60 * 60,
  },
  adapter: PrismaAdapter(db),
  callbacks: {
    async signIn({ user, account, profile, email, credentials }) {
      try {
        if (account && account.type === "oauth") {
          const existingUser = await db.user.findUnique({
            where: { email: user.email! },
            include: { accounts: true },
          });
          if (existingUser) {
            // Check if the user has a credentials-based account
            const hasCredentialsAccount = existingUser.accounts.some(
                (acc) => acc.type === "credentials"
            );

            if (hasCredentialsAccount) {
              logger.error("User has a credentials-based account", hasCredentialsAccount);
              return "/login?error=hasCredentialsAccount";
            }
          }
        }
        if (account && account.type === "credentials") {
          if (user && !user.is_mail_verified) {
            logger.error("Email not verified yet", user);
            return `/login?error=unverifiedMail`;
          }
        }
        if (user?.email && user?.name && user?.image && account && profile) {
          {
            await db.user.create({
              data: {
                email: user.email,
                password: user.name,
                created_on: new Date(),
                is_mail_verified: !!true, // Change is_mail_verified to emailVerified
                profile: {
                  create: {
                    full_name: user.name,
                    mobile_number: "",
                    gender: "OTHER",
                    date_of_birth: "2011-10-05T14:48:00.000Z",
                    picture: {
                      create: {
                        original_name: "profile_picture.png",
                        file_url: user.image,
                        file_name: "profile_picture.png",
                        file_description: "Profile picture",
                        file_type: "image/png",
                        created_on: new Date(),
                      },
                    },
                  },
                },
                accounts: {
                  create: {
                    type: account.type,
                    provider: account.provider,
                    providerAccountId: account.providerAccountId,
                    access_token: account.access_token,
                    refresh_token: account.refresh_token, // Store the refresh token
                    expires_at: account.expires_at,
                    token_type: account.token_type,
                    scope: account.scope,
                    id_token: account.id_token,
                  },
                },
              },
              include: {
                profile: {
                  include: {
                    address: true,
                    picture: true,
                  },
                },
                accounts: true,
              },
            });
          }
        }

        logger.info("Sign in successful", {uuid: user.uuid , email: user.email})
        return true;
      } catch (error:any) {
        logger.error("Sign in failed", { email: credentials?.email, errorData: error.config.data })
        throw error; // Ensure the error propagates to the client
      }
    },

    // !------from authorize(credintial)/signIn(google signUp) the return user will come in this(jwt) fuction------//

    async jwt({ token, user }) {
      try {
        if (user) { 
            
          // console.log(typeof user.id)

          const userId = typeof user.id === "string" ? parseInt(user.id) : user.id;

          var profile = await db.profile.findUnique({
            where: { user_id: userId },
          })

          if (!profile){
            profile = await db.profile.create({
              data: {
                user_id: userId,
                full_name: user.name || "",
                mobile_number: "",
              },
            });
          }

          // console.log(profile)

          token.uuid = user.uuid;
          token.role = user.role;
          token.is_mail_verified = !!user.is_mail_verified;
          token.profileId = profile.id;
        }

        // logger.info("Token generated successfully", { tokenUuid: token?.uuid });
        return token;
      } catch (error:any) {
        logger.error("Failed to generate token", { user: user, errorData: error.config.data });
        throw error; // Ensure the error propagates to the client
      }
    },
    //!------from jwt the return token will come in this(session) fuction------//
    async session({ session, token }) {
      try {
        const existingUser = await db.user.findUnique({
          where: { uuid: token.uuid },
        });
        if (existingUser) {
          // ADD USER Data to session 
            session.user = {
              uuid: token.uuid,
              role: token.role,
              is_mail_verified: existingUser.is_mail_verified,
              profileId: token.profileId,
          }
        }

        // logger.info("Session generated successfully", { sessionExpires: session?.expires });
        return session;
      } catch (error:any) {
        logger.error("Failed to generate session", { token: token, errorData: error.config.data });
        throw error; // Ensure the error propagates to the client
      }
    },
  },

  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID || "",
      clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
      authorization: {
        params: {
          scope:
            "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid",
          access_type: "offline",
          state: generateSessionState(),
        },
      },
    }),
    CredentialsProvider({
      // The name to display on the sign in form (e.g. "Sign in with...")
      name: "Credentials",
      credentials: {
        email: {
          label: "Email",
          type: "email",
          placeholder: "jsmith@gmail.com",
        },
        password: { label: "Password", type: "password" },
      },
      //?----------------- this function will use for credintial signIN----------//
      async authorize(credentials): Promise<any> {
          try {
            // Add logic here to look up the user from the credentials supplied
            if (!credentials?.email || !credentials?.password) {
              logger.warn("Provide credentials", { credentials });
              return null;
            }

            const existingUser = await db.user.findUnique({
              where: { email: credentials?.email },
            });

            if (!existingUser) {
              logger.warn("User not found", { email: credentials?.email });
              return null;
            }

            if (existingUser.password) {
              const passwordMatch = await bcrypt.compare(
                credentials.password,
                existingUser.password
              );

              if (!passwordMatch) {
                logger.warn("Password did not match", { email: credentials?.email });
                return null;
              }
            }

            // logger.info("Authorization completed successfully", { email: credentials?.email });
            return {
              ...existingUser,
              is_mail_verified: existingUser.is_mail_verified,
            };
        } catch (error:any) {
          logger.error("Failed to generate session", { email: credentials?.email, errorData: error.config.data });
          throw error; // Ensure the error propagates to the client
        }
      },
    }),
  ],
};

