import { betterAuth } from 'better-auth'
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
import { bearer } from 'better-auth/plugins'
import { passkey } from '@better-auth/passkey'
import { magicLink } from 'better-auth/plugins/magic-link'
import { organization } from 'better-auth/plugins/organization'
import { useDB } from '../utils/database.ts'
import { getAuthConfig } from '../utils/auth-config.ts'
import {
  user as userTable,
  session as sessionTable,
  account as accountTable,
  verification as verificationTable,
  passkey as passkeyTable
} from '../database/schema/auth.ts'
import {
  sendVerificationEmail as sendVerificationEmailUtil,
  sendPasswordResetEmail as sendPasswordResetEmailUtil,
  sendMagicLinkEmail as sendMagicLinkEmailUtil,
  sendTeamInvitationEmail as sendTeamInvitationEmailUtil
} from '../utils/email.ts'

// Lazily create the Better Auth instance to avoid calling Nuxt composables at module import time
let cachedAuth: ReturnType<typeof betterAuth> | null = null

export function getAuth() {
  if (cachedAuth) return cachedAuth

  const authConfig = getAuthConfig()

  // Build plugins array conditionally
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const plugins: any[] = [
    // Bearer token authentication for Capacitor apps
    // Enables authentication via Authorization header instead of cookies
    bearer(),

    // Passkey/WebAuthn support for passwordless authentication
    passkey(),

    // Magic Link support for email-based passwordless authentication (if enabled)
    ...(authConfig.plugins.magicLink
      ? [magicLink({
          sendMagicLink: async ({ email, url }: { email: string, url: string }) => {
            await sendMagicLinkEmailUtil(email, url)
          }
        })]
      : [])
  ]

  // Add organization plugin conditionally
  if (authConfig.plugins.organization) {
    plugins.push(
      organization({
        async sendInvitationEmail(data) {
          await sendTeamInvitationEmailUtil(
            data.email,
            data.organization.name,
            data.inviter.user.name || data.inviter.user.email,
            `${authConfig.baseURL}/api/auth/organization/accept-invitation?id=${data.invitation.id}`
          )
        }
      })
    )
  }

  cachedAuth = betterAuth({
    baseURL: authConfig.baseURL,
    secret: authConfig.secret,

    trustedOrigins: authConfig.trustedOrigins,

    advanced: {
      // Configure cookies for web browsers (same-origin)
      // For Capacitor apps, we use Bearer tokens instead
      // In production: use secure cookies for same-origin (web browsers)
      // In development: explicitly disable secure cookies for HTTP localhost testing
      useSecureCookies: authConfig.isProduction,
      // In development, don't use __Secure- prefix which requires HTTPS
      // This is critical for HTTP localhost testing
      ...(authConfig.isProduction
        ? {}
        : {
            defaultCookieAttributes: {
              secure: false,
              sameSite: 'lax' as const,
              path: '/',
              httpOnly: true
            }
          })
    },

    // Enable session token in responses for Capacitor compatibility
    session: {
      expiresIn: 60 * 60 * 24 * 7, // 7 days
      updateAge: 60 * 60 * 24, // 1 day
      cookieCache: {
        enabled: true,
        maxAge: 60 * 5 // 5 minutes
      }
    },

    database: drizzleAdapter(useDB(), {
      provider: 'pg',
      // Pass all auth tables to the adapter
      schema: {
        user: userTable,
        session: sessionTable,
        account: accountTable,
        verification: verificationTable,
        passkey: passkeyTable
      }
    }),

    databaseHooks: {
      user: {
        create: {
          after: async (user) => {
            // Notify super admins about new user registration (non-blocking)
            import('../utils/user-notifications').then(({ notifySuperAdminsOfNewUser }) => {
              notifySuperAdminsOfNewUser({
                id: user.id,
                name: user.name,
                email: user.email,
                image: user.image
              }).catch((error: unknown) => {
                console.error('[Better Auth] Failed to notify super admins of new user:', error)
              })
            })
          }
        }
      }
    },

    user: {
      // Include custom fields in user model returned in session
      additionalFields: {
        superAdmin: {
          type: 'boolean',
          defaultValue: false,
          required: false
        },
        banned: {
          type: 'boolean',
          defaultValue: false,
          required: false
        },
        bannedReason: {
          type: 'string',
          required: false
        },
        bannedUntil: {
          type: 'date',
          required: false
        }
      }
    },

    account: {
      // Validate email matches when linking accounts
      accountLinking: {
        enabled: true,
        trustedProviders: ['github', 'google']
      }
    },

    emailAndPassword: {
      enabled: true,
      requireEmailVerification: true,
      sendResetPassword: async ({ user, url }: { user: { email: string, name: string }, url: string }) => {
        await sendPasswordResetEmailUtil(user.email, user.name, url)
      }
    },

    emailVerification: {
      sendOnSignUp: true,
      autoSignInAfterVerification: true,
      sendVerificationEmail: async ({ user, url }: { user: { email: string, name: string }, url: string }) => {
        // Add callbackURL to redirect to dashboard after verification
        const urlWithCallback = new URL(url)
        urlWithCallback.searchParams.set('callbackURL', '/dashboard')
        const finalUrl = urlWithCallback.toString()

        await sendVerificationEmailUtil(user.email, user.name, finalUrl)
      }
    },

    plugins,

    socialProviders: authConfig.socialProviders
  })

  return cachedAuth
}

// Export type for client-side type inference
export type auth = ReturnType<typeof getAuth>
