import type { SessionUser } from '@nexumi/shared';
import { type NextRequest, NextResponse } from 'next/server';
import { exchangeCodeForToken, fetchDiscordUser } from '@/lib/discord-oauth';
import { env } from '@/lib/env';
import { redis } from '@/lib/redis';
import { applySessionCookie, createSession } from '@/lib/session';

function oauthStateKey(state: string): string {
  return `webui:oauth:state:${state}`;
}

function loginRedirect(error: string): NextResponse {
  const url = new URL('/login', env.WEBUI_URL);
  url.searchParams.set('error', error);
  return NextResponse.redirect(url);
}

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const code = searchParams.get('code');
  const state = searchParams.get('state');
  const oauthError = searchParams.get('error');

  if (oauthError) {
    return loginRedirect('access_denied');
  }

  if (!code || !state) {
    return loginRedirect('invalid_request');
  }

  const stateKey = oauthStateKey(state);
  const stateExists = await redis.get(stateKey);
  if (!stateExists) {
    return loginRedirect('invalid_state');
  }
  await redis.del(stateKey);

  let cookieValue: string;
  try {
    const token = await exchangeCodeForToken(code);
    const discordUser = await fetchDiscordUser(token.access_token);

    const user: SessionUser = {
      id: discordUser.id,
      username: discordUser.username,
      globalName: discordUser.global_name ?? null,
      avatar: discordUser.avatar ?? null
    };

    cookieValue = await createSession({
      user,
      accessToken: token.access_token,
      refreshToken: token.refresh_token,
      tokenExpiresAt: Date.now() + token.expires_in * 1000
    });
  } catch (error) {
    console.error('OAuth callback failed', error);
    return loginRedirect('oauth_failed');
  }

  // Cookie must be set on the redirect response — cookies().set() alone is not
  // reliably attached when returning NextResponse.redirect() from a route handler.
  const response = NextResponse.redirect(new URL('/dashboard', env.WEBUI_URL));
  applySessionCookie(response, cookieValue);
  return response;
}
