import { User } from "../../models/User";
import jwt from "jsonwebtoken";
import type {
  OAuthTokenResponse,
  GhostGuildUserInfo,
} from "../../../types/auth";

export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig();
  const query = getQuery(event);

  // Verify state for CSRF protection
  const storedState = getCookie(event, "oauth_state");
  if (!storedState || storedState !== query.state) {
    return sendRedirect(event, "/login?error=invalid_state");
  }

  // Clear the state cookie
  deleteCookie(event, "oauth_state");

  // Exchange authorization code for access token
  try {
    const tokenResponse = await $fetch<OAuthTokenResponse>(
      `${config.ghostguildApiUrl}/oauth/token`,
      {
        method: "POST",
        body: {
          grant_type: "authorization_code",
          code: query.code,
          redirect_uri: `${config.public.siteUrl}/api/auth/callback`,
          client_id: config.ghostguildClientId,
          client_secret: config.ghostguildClientSecret,
        },
      },
    );

    // Get user information from Ghost Guild
    const userInfo = await $fetch<GhostGuildUserInfo>(
      `${config.ghostguildApiUrl}/user/me`,
      {
        headers: {
          Authorization: `Bearer ${tokenResponse.access_token}`,
        },
      },
    );

    // Find or create user in our database
    let user = await User.findOne({ ghostguildId: userInfo.id });

    if (!user) {
      user = await User.create({
        ghostguildId: userInfo.id,
        email: userInfo.email,
        username: userInfo.username,
        displayName: userInfo.displayName || userInfo.username,
        avatar: userInfo.avatar,
        roles: userInfo.roles || ["member"],
        permissions: {
          canEdit: userInfo.roles?.includes("member") || false,
          canModerate: userInfo.roles?.includes("moderator") || false,
          canAdmin: userInfo.roles?.includes("admin") || false,
        },
        lastLogin: new Date(),
      });
    } else {
      // Update existing user
      user.displayName = userInfo.displayName || userInfo.username;
      user.avatar = userInfo.avatar;
      user.roles = userInfo.roles || ["member"];
      user.lastLogin = new Date();
      await user.save();
    }

    // Create JWT token
    const token = jwt.sign(
      {
        userId: user._id,
        username: user.username,
        roles: user.roles,
        permissions: user.permissions,
      },
      config.jwtSecret as string,
      { expiresIn: "7d" },
    );

    // Set JWT as httpOnly cookie
    setCookie(event, "auth-token", token, {
      httpOnly: true,
      secure: true,
      sameSite: "lax",
      maxAge: 60 * 60 * 24 * 7, // 7 days
    });

    // Redirect to dashboard or home
    return sendRedirect(event, "/dashboard");
  } catch (error) {
    console.error("OAuth callback error:", error);
    return sendRedirect(event, "/login?error=authentication_failed");
  }
});
