/**
 * Auth composable using @logto/nuxt
 *
 * Uses useLogtoTokens() for token management with SSR→client sync.
 */

export const useAuth = () => {
  const { getToken, initTokens, idToken } = useLogtoTokens()
  const me = useState<{ id?: string | null } | null>('me', () => null)
  const isAuthenticated = computed(() => !!me.value?.id)
  const loggedIn = isAuthenticated

  /**
   * Get access token for a resource.
   * Tokens are synced from SSR via useState, auto-refreshes if expired.
   */
  const getAccessToken = async (resource: string, _organizationId?: string): Promise<string> => {
    return getToken(resource as Parameters<typeof getToken>[0])
  }

  const getOrganizationToken = getAccessToken

  /**
   * Get ID token.
   * Uses useState for SSR→client sync, falls back to API on client if needed.
   */
  const getIdToken = async (): Promise<string | null> => {
    // SSR or client with synced token
    if (idToken.value) {
      return idToken.value
    }

    // Client fallback - fetch from API
    if (!import.meta.server) {
      const response = await $fetch<{ id_token: string | null }>('/api/auth/id-token')
      return response.id_token
    }

    return null
  }

  /**
   * Get ID token claims (decoded).
   */
  const getIdTokenClaims = async () => {
    const response = await $fetch<{ claims: Record<string, unknown> | null }>('/api/auth/id-token-claims')
    return response.claims
  }

  const signIn = async (_redirectUri?: string) => {
    await navigateTo('/sign-in', { external: true })
  }

  const login = signIn

  const signOut = async (_logoutRedirectUri?: string) => {
    await navigateTo('/sign-out', { external: true })
  }

  const logout = signOut

  const fetch = async () => {
    // Initialize tokens on SSR
    await initTokens()
  }

  return {
    isAuthenticated,
    loggedIn,
    user: me,
    signIn,
    login,
    signOut,
    logout,
    fetch,
    getAccessToken,
    getOrganizationToken,
    getIdToken,
    getIdTokenClaims,
  }
}
