import { keycloakClient } from '~/server/utils/keycloak-client'

export default defineEventHandler(async (event) => {
  const startTime = Date.now()
  const query = getQuery(event)
  const { code, state, error } = query

  console.log('[KEYCLOAK] Callback received:', { 
    code: !!code, 
    state, 
    error,
    requestId: event.node.req.headers['x-request-id'] || 'unknown'
  })

  if (error) {
    const errorMsg = `Authentication failed: ${error}`
    console.error('[KEYCLOAK] OAuth error:', errorMsg)
    
    // Add timing info for debugging
    const duration = Date.now() - startTime
    console.error(`[KEYCLOAK] Failed after ${duration}ms`)
    
    throw createError({
      statusCode: 400,
      statusMessage: errorMsg
    })
  }

  if (!code) {
    const errorMsg = 'No authorization code received'
    console.error('[KEYCLOAK] ' + errorMsg)
    
    const duration = Date.now() - startTime
    console.error(`[KEYCLOAK] Failed after ${duration}ms`)
    
    throw createError({
      statusCode: 400,
      statusMessage: errorMsg
    })
  }

  try {
    console.log('[KEYCLOAK] Starting token exchange...')
    const redirectUri = 'https://client.portnimara.dev/api/auth/keycloak/callback'
    
    // Use the new Keycloak client with retry logic and circuit breaker
    const tokenResponse = await keycloakClient.exchangeCodeForTokens(code as string, redirectUri)
    
    const tokenExchangeDuration = Date.now() - startTime
    console.log(`[KEYCLOAK] Token exchange successful in ${tokenExchangeDuration}ms:`, {
      hasAccessToken: !!tokenResponse.access_token,
      hasRefreshToken: !!tokenResponse.refresh_token,
      expiresIn: tokenResponse.expires_in
    })

    // Get user info with retry logic
    console.log('[KEYCLOAK] Fetching user info...')
    const userInfoStartTime = Date.now()
    
    const userInfo = await keycloakClient.getUserInfo(tokenResponse.access_token)
    
    const userInfoDuration = Date.now() - userInfoStartTime
    console.log(`[KEYCLOAK] User info retrieved in ${userInfoDuration}ms:`, { 
      sub: userInfo.sub, 
      email: userInfo.email,
      username: userInfo.preferred_username,
      name: userInfo.name
    })

    // Set session cookie with proper configuration
    const sessionData = {
      user: {
        id: userInfo.sub,
        email: userInfo.email,
        username: userInfo.preferred_username || userInfo.email,
        name: userInfo.name || userInfo.preferred_username || userInfo.email,
        authMethod: 'keycloak'
      },
      accessToken: tokenResponse.access_token,
      refreshToken: tokenResponse.refresh_token,
      expiresAt: Date.now() + (tokenResponse.expires_in * 1000),
      createdAt: Date.now()
    }

    // Create session cookie with proper session duration (8 hours = 28800 seconds)
    // Not tied to access token lifetime since we'll refresh tokens automatically
    const sessionDuration = 8 * 60 * 60; // 8 hours in seconds
    const cookieDomain = process.env.COOKIE_DOMAIN || '.portnimara.dev';
    
    setCookie(event, 'nuxt-oidc-auth', JSON.stringify(sessionData), {
      httpOnly: true,
      secure: true,
      sameSite: 'lax',
      maxAge: sessionDuration,
      domain: cookieDomain,
      path: '/'
    })

    const totalDuration = Date.now() - startTime
    console.log(`[KEYCLOAK] Authentication completed successfully in ${totalDuration}ms`)
    console.log('[KEYCLOAK] Session cookie set, redirecting to dashboard...')

    // Redirect to dashboard
    await sendRedirect(event, '/dashboard')

  } catch (error: any) {
    const duration = Date.now() - startTime
    console.error(`[KEYCLOAK] Authentication failed after ${duration}ms:`, {
      message: error.message,
      status: error.status,
      statusMessage: error.statusMessage,
      data: error.data
    })
    
    // Log circuit breaker status for debugging
    const circuitStatus = keycloakClient.getCircuitBreakerStatus()
    if (circuitStatus.isOpen) {
      console.error('[KEYCLOAK] Circuit breaker is OPEN:', circuitStatus)
    }
    
    // Provide more specific error messages
    let errorParam = 'auth_failed'
    if (error.status === 503) {
      errorParam = 'service_unavailable'
    } else if (error.status >= 500) {
      errorParam = 'server_error' 
    } else if (error.status === 401 || error.status === 403) {
      errorParam = 'access_denied'
    }
    
    // Redirect to login with specific error
    await sendRedirect(event, `/login?error=${errorParam}`)
  }
})
