import NextAuth, { type AuthOptions } from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import GoogleProvider from 'next-auth/providers/google';
import mysql from 'mysql2/promise';
import bcryptjs from 'bcryptjs';

const pool = mysql.createPool({
  host: process.env.DB_HOST || 'localhost',
  user: process.env.DB_USER || 'root',
  password: process.env.DB_PASSWORD || '',
  database: process.env.DB_NAME || 'perfume_shop',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0,
});

export const authOptions: AuthOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID || '',
      clientSecret: process.env.GOOGLE_CLIENT_SECRET || '',
      allowDangerousEmailAccountLinking: true,
    }),
    CredentialsProvider({
      name: 'Credentials',
      credentials: {
        email: { label: 'Email', type: 'email' },
        password: { label: 'Password', type: 'password' },
      },
      async authorize(credentials) {
        if (!credentials?.email || !credentials?.password) {
          throw new Error('Email and password required');
        }

        try {
          const connection = await pool.getConnection();

          try {
            const [users]: any = await connection.query(
              'SELECT id, first_name, last_name, email, password_hash, is_active FROM users WHERE email = ?',
              [credentials.email]
            );

            if (users.length === 0) {
              throw new Error('Invalid email or password');
            }

            const user = users[0];

            if (!user.is_active) {
              throw new Error('Account is inactive');
            }

            const isPasswordValid = await bcryptjs.compare(
              credentials.password,
              user.password_hash
            );

            if (!isPasswordValid) {
              throw new Error('Invalid email or password');
            }

            // Update last login
            await connection.query(
              'UPDATE users SET last_login = NOW() WHERE id = ?',
              [user.id]
            );

            return {
              id: user.id.toString(),
              name: `${user.first_name} ${user.last_name}`,
              firstName: user.first_name,
              lastName: user.last_name,
              email: user.email,
            };
          } finally {
            connection.release();
          }
        } catch (error: any) {
          throw new Error(error.message || 'Authentication failed');
        }
      },
    }),
  ],
  callbacks: {
    async signIn({ user, account, profile }: any) {
      // If user signs in with Google, create/update in database
      if (account?.provider === 'google' && profile) {
        try {
          const connection = await pool.getConnection();
          try {
            // Check if user exists
            const [existingUsers]: any = await connection.query(
              'SELECT id FROM users WHERE email = ?',
              [user.email]
            );

            const profilePicture = (profile as any).picture || null;

            if (existingUsers.length === 0) {
              // Create new user from Google profile
              const firstName = (profile as any).given_name || user.name?.split(' ')[0] || 'User';
              const lastName = (profile as any).family_name || user.name?.split(' ')[1] || '';

              const [result]: any = await connection.query(
                `INSERT INTO users (first_name, last_name, email, password_hash, is_active, role, profile_picture, created_at, updated_at)
                 VALUES (?, ?, ?, ?, 1, 'customer', ?, NOW(), NOW())`,
                [firstName, lastName, user.email, 'oauth_google', profilePicture]
              );

              // Store the DB ID in the user object so JWT callback can use it
              user.id = result.insertId.toString();
            } else {
              // Update existing user
              await connection.query(
                'UPDATE users SET last_login = NOW(), profile_picture = ? WHERE email = ?',
                [profilePicture, user.email]
              );

              // Set the correct DB ID
              user.id = existingUsers[0].id.toString();
            }
          } finally {
            connection.release();
          }
        } catch (error) {
          return false;
        }
      }
      return true;
    },
    async jwt({ token, user, account, profile }: any) {
      // When user object exists (initial signin)
      if (user) {
        token.id = user.id;
        token.firstName = (user as any).firstName;
        token.lastName = (user as any).lastName;
        token.email = user.email;
        token.image = user.image;
      }

      // For Google OAuth, ALWAYS fetch the correct DB ID based on email
      if (account?.provider === 'google' && token.email) {
        token.firstName = (profile as any).given_name || token.firstName || user?.name?.split(' ')[0];
        token.lastName = (profile as any).family_name || token.lastName || user?.name?.split(' ')[1];
        token.image = (profile as any).picture || token.image;

        try {
          const connection = await pool.getConnection();
          try {
            const [users]: any = await connection.query(
              'SELECT id, first_name, last_name, profile_picture FROM users WHERE email = ?',
              [token.email]
            );

            if (users && users.length > 0) {
              token.id = users[0].id.toString(); // Use the correct DB ID, not Google ID
              token.firstName = users[0].first_name;
              token.lastName = users[0].last_name;
              token.image = users[0].profile_picture || token.image;
            }
          } finally {
            connection.release();
          }
        } catch (error) {
        }
      }

      return token;
    },
    async session({ session, token }: any) {
      if (session.user) {
        session.user.id = token.id as string;
        (session.user as any).firstName = token.firstName;
        (session.user as any).lastName = token.lastName;
        session.user.image = token.image;
      }
      return session;
    },
  },
  pages: {
    signIn: '/login',
    error: '/login',
  },
  session: {
    strategy: 'jwt' as const,
    maxAge: 7 * 24 * 60 * 60, // 7 days
    updateAge: 24 * 60 * 60, // 1 day
  },
  secret: process.env.NEXTAUTH_SECRET,
};

export default NextAuth(authOptions);
