const config = useRuntimeConfig();
// Define session duration (default to 1 hour if not specified in config)
const SESSION_DURATION = (config.sessionDurationHours || 1) * 60 * 60 * 24;

// This is the MAIN SESSION duration. It controls how long a user stays logged in.
// Current configuration: 1 hour (3600 seconds).

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

    console.log("🔄 === KEYCLOAK CALLBACK STARTED ===");
    console.log("📋 Query parameters:", query);

    const code = query.code as string;
    const state = query.state as string;
    const error = query.error as string;
    const storedState = getCookie(event, "oauth_state");

    if (error) {
      console.error("❌ OAuth error from Keycloak:", error);
      const errorDescription = query.error_description as string;
      console.error("❌ Error description:", errorDescription);

      const errorMsg = encodeURIComponent(
        `Keycloak error: ${error} - ${errorDescription || "Please try again"}`,
      );
      return sendRedirect(event, `/LoginPage?error=${errorMsg}`);
    }

    console.log("📝 Code received:", !!code);
    console.log("🎲 State from URL:", state);
    console.log("🎲 State from cookie:", storedState);
    console.log("🎲 State validation:", state === storedState);

    if (!state || state !== storedState) {
      console.error("❌ Invalid state parameter - possible CSRF attack");
      console.error("   Expected:", storedState);
      console.error("   Received:", state);

      const errorMsg = encodeURIComponent(
        "Security validation failed. Please try logging in again.",
      );
      return sendRedirect(event, `/LoginPage?error=${errorMsg}`);
    }

    deleteCookie(event, "oauth_state");

    if (!code) {
      console.error("❌ Authorization code not provided");
      const errorMsg = encodeURIComponent(
        "No authorization code received from Keycloak.",
      );
      return sendRedirect(event, `/LoginPage?error=${errorMsg}`);
    }

    // Validate Keycloak configuration
    if (!config.keycloakIssuer) {
      console.error("❌ KEYCLOAK_ISSUER is not configured");
      const errorMsg = encodeURIComponent(
        "Keycloak server is not configured. Please contact administrator.",
      );
      return sendRedirect(event, `/LoginPage?error=${errorMsg}`);
    }

    if (!config.keycloakClientId || !config.keycloakClientSecret) {
      console.error("❌ Keycloak client credentials are not configured");
      const errorMsg = encodeURIComponent(
        "Keycloak client credentials are missing. Please contact administrator.",
      );
      return sendRedirect(event, `/LoginPage?error=${errorMsg}`);
    }

    const tokenUrl = `${config.keycloakIssuer}/protocol/openid-connect/token`;
    const redirectUri = `${config.public.authUrl}/api/auth/keycloak-callback`;

    console.log("🔗 Token URL:", tokenUrl);
    console.log("🔗 Redirect URI:", redirectUri);
    console.log(
      "🔑 Client ID:",
      config.keycloakClientId ? "***configured***" : "MISSING",
    );

    const tokenPayload = new URLSearchParams({
      grant_type: "authorization_code",
      client_id: config.keycloakClientId,
      client_secret: config.keycloakClientSecret,
      code,
      redirect_uri: redirectUri,
    });

    let tokenResponse;
    try {
      // Create abort controller for timeout (compatible with all Node.js versions)
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout

      tokenResponse = await fetch(tokenUrl, {
        method: "POST",
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
        body: tokenPayload,
        signal: controller.signal,
      });

      clearTimeout(timeoutId);
    } catch (fetchError: any) {
      console.error("❌ Fetch error details:");
      console.error("   - Error type:", fetchError.name);
      console.error("   - Error message:", fetchError.message);
      console.error("   - Token URL attempted:", tokenUrl);

      // Provide more specific error messages
      let errorMsg = "Failed to connect to authentication server.";
      if (
        fetchError.name === "AbortError" ||
        fetchError.message.includes("timeout")
      ) {
        errorMsg = "Authentication server timeout. Please try again.";
      } else if (
        fetchError.message.includes("ENOTFOUND") ||
        fetchError.message.includes("getaddrinfo")
      ) {
        errorMsg =
          "Cannot reach authentication server. Please check network connection.";
      } else if (fetchError.message.includes("ECONNREFUSED")) {
        errorMsg =
          "Authentication server refused connection. Server may be down.";
      } else if (
        fetchError.message.includes("certificate") ||
        fetchError.message.includes("SSL")
      ) {
        errorMsg = "SSL certificate error. Please contact administrator.";
      }

      const encodedError = encodeURIComponent(errorMsg);
      return sendRedirect(event, `/LoginPage?error=${encodedError}`);
    }

    if (!tokenResponse.ok) {
      const errorText = await tokenResponse.text();
      console.error("❌ Token exchange failed:", errorText);
      const errorMsg = encodeURIComponent(
        `Token exchange failed: ${tokenResponse.status} - Please check Keycloak configuration`,
      );
      return sendRedirect(event, `/LoginPage?error=${errorMsg}`);
    }

    const tokens = await tokenResponse.json();

    // Parse token payloads for immediate availability
    let accessTokenPayload;
    let idTokenPayloadFull;
    let refreshTokenPayload;
    try {
      accessTokenPayload = JSON.parse(
        Buffer.from(tokens.access_token.split(".")[1], "base64").toString(),
      );
      idTokenPayloadFull = JSON.parse(
        Buffer.from(tokens.id_token.split(".")[1], "base64").toString(),
      );
      if (tokens.refresh_token) {
        refreshTokenPayload = JSON.parse(
          Buffer.from(tokens.refresh_token.split(".")[1], "base64").toString(),
        );
      }
    } catch (parseError) {
      console.error("❌ Failed to parse token payloads:", parseError);
      const errorMsg = encodeURIComponent("Invalid token format");
      return sendRedirect(event, `/LoginPage?error=${errorMsg}`);
    }

    // Determine session expiration from refresh token (preferred) or default
    const expiresAt = refreshTokenPayload?.exp 
      ? refreshTokenPayload.exp * 1000 
      : Date.now() + SESSION_DURATION * 1000;

    const createdAt = refreshTokenPayload?.iat
      ? refreshTokenPayload.iat * 1000
      : Date.now();

    // Create session data
    const sessionData = {
      user: {
        id: idTokenPayloadFull.sub,
        email: idTokenPayloadFull.email,
        name: idTokenPayloadFull.name || idTokenPayloadFull.preferred_username,
        preferred_username: idTokenPayloadFull.preferred_username,
      },
      accessToken: tokens.access_token,
      idToken: tokens.id_token,
      refreshToken: tokens.refresh_token,
      expiresAt: expiresAt,
      createdAt: createdAt,
      scope: accessTokenPayload.scope || "openid email profile",
      status: "authenticated",
    };

    // Store session in server-side store and get session ID
    const { createSession } = await import('~/server/utils/sessionStore');
    const sessionId = createSession(sessionData);

    // Determine if we should use secure cookies
    const isSecure =
      process.env.NODE_ENV === "production" &&
      event.node.req.headers["x-forwarded-proto"] === "https";

    console.log("🔗 Setting session ID cookie");
    console.log("⏱️ Session duration:", SESSION_DURATION, "seconds");

    const cookieOptions: any = {
      httpOnly: true,
      secure: isSecure,
      sameSite: "lax" as const,
      maxAge: SESSION_DURATION,
      path: "/",
    };

    // Store only session ID in cookie (small size, ~64 bytes)
    setCookie(event, "user_session", sessionId, cookieOptions);

    console.log("✅ Session ID cookie created successfully");
    console.log("🍪 Cookie details:");
    console.log("   - Name: user_session");
    console.log("   - Size:", sessionId.length, "bytes");
    console.log("   - Path: /");
    console.log("   - Secure:", isSecure);
    console.log("   - SameSite: lax");
    console.log("   - HttpOnly: true");
    console.log("   - MaxAge:", SESSION_DURATION, "seconds");
    console.log("   - Host:", event.node.req.headers.host);

    // Auto-sync user data to database (first time login check)
    // Pass session createdAt as loginTime to sync function
    try {
      const { syncUserFromTokens } = await import("~/server/utils/userSync");
      const result = syncUserFromTokens(
        tokens.id_token,
        tokens.access_token,
        sessionData.createdAt,
      );
      console.log(
        `✅ User auto-sync on login: ${result.action} - ${result.message}`,
      );
    } catch (syncError: any) {
      // Don't fail the login if sync fails, just log it
      console.error("⚠️ Failed to auto-sync user on login:", syncError);
    }

    // IMPORTANT: Ensure cookie is set before redirect
    // The cookie should be in the Set-Cookie header of the redirect response
    console.log(
      "↪️ Redirecting to dashboard with cookie in response headers...",
    );

    // Note: In H3/Nitro, setCookie automatically adds Set-Cookie header to response
    // The cookie will be available in the browser after the redirect
    // We can't verify it in the same request, but it should be set correctly

    // Use sendRedirect - it should include the Set-Cookie header
    // The browser will receive the cookie and include it in the next request
    return sendRedirect(event, "/dashboard?authenticated=true", 302);
  } catch (error: any) {
    console.error("❌ === CALLBACK ERROR ===");
    console.error("❌ Error message:", error.message);
    console.error("❌ Error stack:", error.stack);
    console.error("❌ ==================");

    const errorMsg = encodeURIComponent(
      `Authentication failed: ${error.message}`,
    );
    return sendRedirect(event, `/LoginPage?error=${errorMsg}`);
  }
});
