import { useOidcAuth } from '#imports'

function decodeJwt(token?: string) {
  if (!token) {
    return null
  }
  const payload = token.split('.')[1]
  if (!payload) {
    return null
  }

  try {
    const normalized = payload.replace(/-/g, '+').replace(/_/g, '/')
    const json =
      typeof window === 'undefined'
        ? Buffer.from(normalized, 'base64').toString('utf8')
        : atob(normalized)
    return JSON.parse(json)
  }
  catch {
    return null
  }
}

export const useAuth = () => {
  const auth = useOidcAuth()
  const isAuthenticated = auth.loggedIn

  const ensureSession = async () => {
    if (!auth.loggedIn.value) {
      await auth.fetch()
    }
  }

  const getIdToken = async () => {
    await ensureSession()
    return auth.user.value?.idToken
  }

  const getIdTokenClaims = async () => {
    await ensureSession()
    const token = auth.user.value?.idToken
    if (token) {
      return decodeJwt(token)
    }
    return auth.user.value?.claims || auth.user.value?.userInfo || null
  }

  // Кеш для access tokens по resource+organizationId
  const accessTokenCache = new Map<string, { token: string; expiresAt: number }>()

  const getAccessToken = async (resource: string, organizationId?: string): Promise<string> => {
    await ensureSession()

    // Ключ кеша включает organizationId
    const cacheKey = organizationId ? `${resource}:${organizationId}` : resource

    // Проверяем кеш (с запасом 60 секунд)
    const cached = accessTokenCache.get(cacheKey)
    if (cached && cached.expiresAt > Date.now() + 60000) {
      return cached.token
    }

    // Обмениваем refresh token на JWT для resource
    const body: { resource: string; organization_id?: string } = { resource }
    if (organizationId) {
      body.organization_id = organizationId
    }

    const response = await $fetch<{
      access_token: string
      expires_in: number
    }>('/api/auth/exchange-token', {
      method: 'POST',
      body
    })

    // Кешируем
    accessTokenCache.set(cacheKey, {
      token: response.access_token,
      expiresAt: Date.now() + response.expires_in * 1000
    })

    return response.access_token
  }

  const getOrganizationToken = getAccessToken

  const signIn = async (redirectUri?: string) => {
    const params = redirectUri ? { redirectUri } : undefined
    await auth.login(undefined, params)
  }

  const signOut = async (logoutRedirectUri?: string) => {
    await auth.logout(undefined, logoutRedirectUri)
  }

  return {
    ...auth,
    isAuthenticated,
    signIn,
    signOut,
    getIdToken,
    getIdTokenClaims,
    getAccessToken,
    getOrganizationToken,
  }
}
