import type {
  ClientOptions,
  InferSessionFromClient,
  InferUserFromClient,
  createAuthClient
} from 'better-auth/client'
import type {
  adminClient,
  magicLinkClient,
  organizationClient
} from 'better-auth/client/plugins'
import type { passkeyClient } from '@better-auth/passkey/client'

/**
 * Better Auth client configuration with all possible plugins
 * This type represents the full client configuration including:
 * - admin: Always enabled
 * - passkey: Always enabled
 * - magicLink: Conditionally enabled based on config
 * - organization: Conditionally enabled based on config
 */
export type AuthClientOptions = ClientOptions & {
  plugins?: Array<
    | ReturnType<typeof adminClient>
    | ReturnType<typeof passkeyClient>
    | ReturnType<typeof magicLinkClient>
    | ReturnType<typeof organizationClient>
  >
}

/**
 * Properly typed Better Auth client with all plugins
 * This type represents the client instance returned by createAuthClient
 * with all possible plugins included.
 *
 * Note: Due to conditional plugin loading at runtime, TypeScript can't perfectly
 * infer all plugin methods at compile time. The type includes all possible plugins,
 * but some methods may need runtime checks or type assertions.
 */
export type AuthClient = ReturnType<typeof createAuthClient<AuthClientOptions>> & {
  // Ensure passkey is always available (it's always loaded)
  passkey: {
    listUserPasskeys: () => Promise<unknown>
    addPasskey: (payload: { name: string }) => Promise<unknown>
    deletePasskey: (payload: { id: string }) => Promise<unknown>
  }
  // Ensure admin is always available (it's always loaded)
  admin: Record<string, unknown>
}

/**
 * Session type inferred from the Better Auth client configuration
 * Includes all custom fields (superAdmin, banned, bannedUntil, etc.)
 */
export type AuthSession = InferSessionFromClient<AuthClientOptions>

/**
 * User type inferred from the Better Auth client configuration
 * Includes all custom fields (superAdmin, banned, bannedUntil, etc.)
 */
export type AuthUser = InferUserFromClient<AuthClientOptions>

/**
 * Helper type for Better Auth client methods
 * Provides type-safe access to client methods
 */
export type AuthClientMethods = {
  signIn: AuthClient['signIn']
  signUp: AuthClient['signUp']
  signOut: AuthClient['signOut']
  forgetPassword: (payload: { email: string, redirectTo?: string }) => Promise<{ error?: { message: string } }>
  resetPassword: AuthClient['resetPassword']
  changePassword: AuthClient['changePassword']
  passkey: AuthClient['passkey']
  admin: AuthClient['admin']
}
