import NextAuth from 'next-auth'
import Apple from 'next-auth/providers/apple'
import Credentials from 'next-auth/providers/credentials'
import Facebook from 'next-auth/providers/facebook'
import Google from 'next-auth/providers/google'
import { authConfig } from './auth.config'

function oauthProviders() {
  const list = []
  if (process.env.AUTH_GOOGLE_ID?.trim() && process.env.AUTH_GOOGLE_SECRET?.trim()) {
    list.push(
      Google({
        clientId: process.env.AUTH_GOOGLE_ID,
        clientSecret: process.env.AUTH_GOOGLE_SECRET,
      }),
    )
  }
  if (process.env.AUTH_FACEBOOK_ID?.trim() && process.env.AUTH_FACEBOOK_SECRET?.trim()) {
    list.push(
      Facebook({
        clientId: process.env.AUTH_FACEBOOK_ID,
        clientSecret: process.env.AUTH_FACEBOOK_SECRET,
      }),
    )
  }
  if (process.env.AUTH_APPLE_ID?.trim() && process.env.AUTH_APPLE_SECRET?.trim()) {
    list.push(
      Apple({
        clientId: process.env.AUTH_APPLE_ID,
        clientSecret: process.env.AUTH_APPLE_SECRET,
      }),
    )
  }
  return list
}

export const { handlers, auth, signIn, signOut } = NextAuth({
  ...authConfig,
  providers: [
    Credentials({
      id: 'credentials',
      name: 'E-mail i hasło',
      credentials: {
        email: { label: 'E-mail', type: 'email' },
        password: { label: 'Hasło', type: 'password' },
      },
      async authorize(credentials) {
        const [{ findUserByEmail }, { compare }] = await Promise.all([
          import('@/lib/users'),
          import('bcryptjs'),
        ])
        const email = credentials?.email
        const password = credentials?.password
        if (typeof email !== 'string' || typeof password !== 'string') return null

        const user = await findUserByEmail(email)
        if (!user?.password) return null

        const ok = await compare(password, user.password)
        if (!ok) return null

        return {
          id: user.id,
          email: user.email,
          name: user.name,
        }
      },
    }),
    ...oauthProviders(),
  ],
  callbacks: {
    ...authConfig.callbacks,
    async jwt({ token, user, account }) {
      if (user) {
        if (account?.provider === 'credentials' && typeof user.id === 'string') {
          token.sub = user.id
          token.email = user.email
        } else if (user.email && account && account.provider !== 'credentials') {
          const { ensureOAuthUser } = await import('@/lib/users')
          const { id } = await ensureOAuthUser(String(user.email), user.name ?? null)
          token.sub = id
          token.email = String(user.email).toLowerCase()
        }
      }
      if (token.sub) {
        const { isUserAdmin } = await import('@/lib/admin-auth')
        token.isAdmin = await isUserAdmin(token.sub, token.email as string | undefined)
      }
      return token
    },
  },
})
