import { NextRequest, NextResponse } from 'next/server'
import { cookies } from 'next/headers'
import { prisma } from '@/lib/db'
import { createSession } from '@/lib/auth'
import { createAuditLog } from '@/lib/audit'

interface DiscordUser {
  id: string
  username: string
  discriminator: string
  avatar: string | null
  email?: string
}

interface DiscordTokenResponse {
  access_token: string
  token_type: string
  expires_in: number
  refresh_token: string
  scope: string
}

export async function GET(request: NextRequest) {
  // Use DISCORD_REDIRECT_URI directly, fallback to constructed URL
  const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'
  const redirectUri = process.env.DISCORD_REDIRECT_URI || `${baseUrl}/api/auth/discord/callback`
  
  console.log('[Auth Callback] Base URL:', baseUrl)
  console.log('[Auth Callback] Redirect URI:', redirectUri)

  try {
    const { searchParams } = new URL(request.url)
    const code = searchParams.get('code')
    const error = searchParams.get('error')

    if (error) {
      console.error('[Auth] Discord OAuth error:', error)
      return NextResponse.redirect(new URL(`/auth/login?error=${error}`, baseUrl))
    }

    if (!code) {
      return NextResponse.redirect(new URL('/auth/login?error=no_code', baseUrl))
    }

    // Get Discord OAuth settings directly from environment (most reliable)
    const clientId = process.env.DISCORD_CLIENT_ID
    const clientSecret = process.env.DISCORD_CLIENT_SECRET

    console.log('[Auth Callback] Client ID:', clientId ? `${clientId.substring(0, 5)}...` : 'NOT SET')
    console.log('[Auth Callback] Client Secret:', clientSecret ? 'SET' : 'NOT SET')

    if (!clientId || !clientSecret) {
      console.error('[Auth] Discord credentials not configured')
      return NextResponse.redirect(new URL('/auth/login?error=discord_not_configured', baseUrl))
    }

    const callbackUrl = redirectUri

    // Exchange code for tokens
    const tokenResponse = await fetch('https://discord.com/api/oauth2/token', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: new URLSearchParams({
        client_id: clientId,
        client_secret: clientSecret,
        code,
        grant_type: 'authorization_code',
        redirect_uri: callbackUrl,
      }),
    })

    if (!tokenResponse.ok) {
      const errorText = await tokenResponse.text()
      console.error('[Auth] Token exchange failed:', errorText)
      return NextResponse.redirect(new URL('/auth/login?error=token_exchange_failed', baseUrl))
    }

    const tokens: DiscordTokenResponse = await tokenResponse.json()

    // Get user info from Discord
    const userResponse = await fetch('https://discord.com/api/users/@me', {
      headers: {
        Authorization: `Bearer ${tokens.access_token}`,
      },
    })

    if (!userResponse.ok) {
      console.error('[Auth] Failed to get Discord user info')
      return NextResponse.redirect(new URL('/auth/login?error=user_fetch_failed', baseUrl))
    }

    const discordUser: DiscordUser = await userResponse.json()
    console.log('[Auth Callback] Discord user fetched:', discordUser.username, discordUser.id)

    // Find or create user
    let user = await prisma.user.findUnique({
      where: { discordId: discordUser.id },
    })

    if (!user) {
      // Create new user
      console.log('[Auth Callback] Creating new user for Discord ID:', discordUser.id)
      user = await prisma.user.create({
        data: {
          discordId: discordUser.id,
          username: discordUser.username,
          discriminator: discordUser.discriminator,
          avatar: discordUser.avatar,
          email: discordUser.email,
          role: 'USER',
        },
      })
      console.log('[Auth Callback] New user created with ID:', user.id)
    } else {
      console.log('[Auth Callback] Existing user found:', user.id)
      // Update existing user
      user = await prisma.user.update({
        where: { id: user.id },
        data: {
          username: discordUser.username,
          discriminator: discordUser.discriminator,
          avatar: discordUser.avatar,
          email: discordUser.email,
          lastLoginAt: new Date(),
        },
      })
    }

    // Store/update Discord tokens
    await prisma.discordAccount.upsert({
      where: { userId: user.id },
      create: {
        userId: user.id,
        accessToken: tokens.access_token,
        refreshToken: tokens.refresh_token,
        tokenExpires: new Date(Date.now() + tokens.expires_in * 1000),
      },
      update: {
        accessToken: tokens.access_token,
        refreshToken: tokens.refresh_token,
        tokenExpires: new Date(Date.now() + tokens.expires_in * 1000),
      },
    })

    // Create session
    const sessionToken = await createSession(user)
    console.log('[Auth Callback] Session token created for user:', user.id)

    // Set cookie - use secure only on HTTPS
    const isHttps = baseUrl.startsWith('https')
    const cookieStore = await cookies()
    cookieStore.set('session', sessionToken, {
      httpOnly: true,
      secure: isHttps, // Only secure on HTTPS, not HTTP
      sameSite: 'lax',
      maxAge: 60 * 60 * 24 * 7, // 7 days
      path: '/',
    })
    console.log('[Auth Callback] Cookie set, secure:', isHttps)

    // Audit log
    await createAuditLog({
      userId: user.id,
      action: 'USER_LOGIN',
      category: 'AUTH',
      details: {
        discordId: discordUser.id,
        username: discordUser.username,
      },
      ipAddress: request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || undefined,
      userAgent: request.headers.get('user-agent') || undefined,
      discordLog: {
        title: 'User Login',
        description: `${discordUser.username} logged in`,
        fields: [
          { name: 'Discord ID', value: discordUser.id, inline: true },
          { name: 'Role', value: user.role, inline: true },
        ],
      },
    })

    return NextResponse.redirect(new URL('/dashboard', baseUrl))
  } catch (error) {
    console.error('[Auth] Discord callback error:', error)
    return NextResponse.redirect(new URL('/auth/login?error=callback_failed', baseUrl))
  }
}
