import { createAuthManager } from './core/auth-manager'
import { createSupabaseAuthProvider } from './providers/supabase'
import { CookieSessionStorage } from './utils/session'
import type { AuthConfig } from './types'

const supabaseUrl = import.meta.env.PUBLIC_SUPABASE_URL
const supabaseAnonKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY

if (!supabaseUrl || !supabaseAnonKey) {
  throw new Error('Missing required Supabase environment variables')
}

const authProvider = createSupabaseAuthProvider(supabaseUrl, supabaseAnonKey)

const authConfig: AuthConfig = {
  provider: authProvider,
  persistSession: true,
  autoRefreshToken: true,
  sessionKey: 'bct_auth_session',
  cookieOptions: {
    httpOnly: true,
    secure: import.meta.env.PROD,
    sameSite: 'lax',
    path: '/',
    maxAge: 60 * 60 * 24 * 7, // 7 days
  },
}

export const authManager = createAuthManager(authConfig)

export * from './types'
export * from './hooks'
export * from './components'
export * from './guards'
export * from './utils'
export * from './providers'
export * from './core'

// Compatibility layer for existing code
import type { AstroCookies } from 'astro'
import type { User, Session } from '@supabase/supabase-js'
import { createSupabaseServerClient, createSupabaseServerClientFromRequest } from '../supabase-ssr'

// Auth context interface for compatibility
export interface AuthContext {
  user: User
  session: Session
  isAdmin: boolean
  isSuperAdmin: boolean
  organizationId: string | null
}

/**
 * Compatibility function for existing verifyAuth usage
 * This allows existing pages to continue working while they migrate to the new auth system
 */
export async function verifyAuth(requestOrCookies: Request | AstroCookies): Promise<AuthContext | null> {
  try {
    // Create appropriate Supabase client based on input type
    const supabase = requestOrCookies instanceof Request 
      ? createSupabaseServerClientFromRequest(requestOrCookies)
      : createSupabaseServerClient(requestOrCookies)
    
    // Get session from cookies
    const { data: { session }, error } = await supabase.auth.getSession()
    
    if (error || !session) {
      // Try Authorization header as fallback (only for Request objects)
      if (requestOrCookies instanceof Request) {
        const authHeader = requestOrCookies.headers.get('Authorization')
        if (authHeader && authHeader.startsWith('Bearer ')) {
          const accessToken = authHeader.substring(7)
          const { data: { user }, error: tokenError } = await supabase.auth.getUser(accessToken)
          
          if (tokenError || !user) {
            return null
          }
          
          // Create a minimal session for bearer token auth
          return await buildAuthContext(user, accessToken, supabase)
        }
      }
      
      // No valid session or token found
      return null
    }
    
    // Build and return auth context
    return await buildAuthContext(session.user, session.access_token, supabase)
  } catch (error) {
    console.error('[Auth] Verification error:', error)
    return null
  }
}

/**
 * Require admin authentication for API routes
 */
export async function requireAdmin(request: Request): Promise<AuthContext> {
  const auth = await verifyAuth(request)
  
  if (!auth) {
    throw new Error('Authentication required')
  }
  
  if (!auth.isAdmin) {
    throw new Error('Admin access required')
  }
  
  return auth
}

/**
 * Rate limiting for API endpoints
 */
const rateLimitStore = new Map<string, { count: number; resetTime: number }>()

export function checkRateLimit(identifier: string, limit: number, windowMs: number): boolean {
  const now = Date.now()
  const key = identifier
  
  const record = rateLimitStore.get(key)
  
  if (!record || now > record.resetTime) {
    // Reset or create new record
    rateLimitStore.set(key, { count: 1, resetTime: now + windowMs })
    return true
  }
  
  if (record.count >= limit) {
    return false
  }
  
  record.count++
  return true
}

/**
 * Get client IP address from request
 */
export function getClientIP(request: Request): string {
  return request.headers.get('x-forwarded-for') || 
         request.headers.get('x-real-ip') || 
         'unknown'
}

/**
 * Require authentication for API routes
 */
export async function requireAuth(request: Request): Promise<AuthContext> {
  const auth = await verifyAuth(request)
  
  if (!auth) {
    throw new Error('Authentication required')
  }
  
  return auth
}

/**
 * Create standardized auth response
 */
export function createAuthResponse(message: string, status: number = 401) {
  return new Response(JSON.stringify({ error: message }), {
    status,
    headers: { 'Content-Type': 'application/json' }
  })
}

/**
 * Build auth context with user data from database
 */
async function buildAuthContext(
  user: User,
  accessToken: string,
  supabaseClient: any
): Promise<AuthContext> {
  // Get additional user data from database
  const { data: userRecord, error: dbError } = await supabaseClient
    .from('users')
    .select('role, organization_id')
    .eq('id', user.id)
    .single()

  if (dbError) {
    console.error('[Auth] Database lookup error:', dbError)
    // Return basic auth context even if DB lookup fails
    return {
      user,
      session: {
        access_token: accessToken,
        user,
        expires_at: Date.now() / 1000 + 3600, // 1 hour from now
        expires_in: 3600,
        refresh_token: '',
        token_type: 'bearer',
      } as Session,
      isAdmin: false,
      isSuperAdmin: false,
      organizationId: null,
    }
  }

  return {
    user,
    session: {
      access_token: accessToken,
      user,
      expires_at: Date.now() / 1000 + 3600, // 1 hour from now
      expires_in: 3600,
      refresh_token: '',
      token_type: 'bearer',
    } as Session,
    isAdmin: userRecord?.role === 'admin',
    isSuperAdmin: userRecord?.role === 'super_admin',
    organizationId: userRecord?.organization_id || null,
  }
}