/**
 * @module routes/api/v1/auth/google
 * @file Defines the routes for Google OAuth 2.0 authentication.
 */

const express = require('express');
const passport = require('passport');

const { updateOrCreateToken } = require('../../../helpers/token-helper');
const { createAuthErrorResponse } = require('../../../helpers/auth-error-handler');

const googleAuthRouter = express.Router();

/**
 * Initiates the Google OAuth 2.0 authentication flow. This route redirects the user to Google's
 * login and consent screen.
 */
googleAuthRouter.get('/', passport.authenticate('google', { scope: ['profile', 'email'] }));

googleAuthRouter.get(
  '/callback',
  (req, res, next) => {
    passport.authenticate('google', { session: false }, (err, user, info) => {
      // Handle authentication errors
      if (err) {
        console.error('[Google OAuth Callback Error]', {
          type: err.type || 'UNKNOWN',
          message: err.message,
          provider: err.provider || 'Google',
        });

        const errorResponse = createAuthErrorResponse(err, 'Google');
        return res.status(401).json(errorResponse);
      }

      // Handle authentication failure (no user returned)
      if (!user) {
        return res.status(401).json({
          success: false,
          error: {
            message:
              info?.message ||
              'Google authentication failed. Please try again or use a different sign-in method.',
            type: 'PROVIDER_ERROR',
            canRetry: true,
            provider: 'Google',
          },
        });
      }

      // Authentication successful, attach user to request
      req.user = user;
      return next();
    })(req, res, next);
  },

  /**
   * Handles the callback from Google after successful authentication. It receives the user profile
   * from Passport, generates tokens (access + refresh), and returns them to the client.
   *
   * @param {import('express').Request} req The Express request object. Passport attaches the
   *   authenticated user to `req.user`.
   * @param {import('express').Response} res The Express response object.
   * @param {import('express').NextFunction} next The Express next function for error handling.
   * @returns {Promise<import('express').Response>} A JSON response with success, tokens, and user
   *   details.
   */
  async (req, res, next) => {
    /**
     * @typedef {object} AuthenticatedUser
     * @property {string} id User's unique identifier
     * @property {string | null} google_id Google OAuth ID
     * @property {string} email_address User's email address
     * @property {string} firstname User's first name
     * @property {string} lastname User's last name
     * @property {boolean} is_google Whether user signed up via Google
     * @property {boolean} is_host Whether user is a host
     * @property {boolean} has_pending_host_application Whether user has pending host application
     * @property {string | null} image User's profile image
     * @property {string | null} phone_no User's phone number
     * @property {string | null} valid_id_image User's valid ID image
     * @property {Date} createdAt Account creation timestamp
     * @property {Date} updatedAt Last update timestamp
     */

    const { user } = req;

    if (!user) {
      return res.status(401).json({
        success: false,
        error: {
          message: 'Authentication failed: User profile not found.',
          type: 'PROVIDER_ERROR',
          canRetry: true,
          provider: 'Google',
        },
      });
    }

    try {
      /** @type {AuthenticatedUser} */
      const authenticatedUser = user;

      const { token, refreshToken } = await updateOrCreateToken(authenticatedUser.id, req, {
        isHost: authenticatedUser.is_host,
        hasPendingApplication: authenticatedUser.has_pending_host_application,
      });

      return res.json({
        success: true,
        token,
        refreshToken,
        user: {
          id: authenticatedUser.id,
          image: authenticatedUser.image,
          firstname: authenticatedUser.firstname,
          lastname: authenticatedUser.lastname,
          email: authenticatedUser.email_address,
          phoneNo: authenticatedUser.phone_no,
          isHost: authenticatedUser.is_host,
          hasValidId: !!authenticatedUser?.valid_id_image,
          hasPendingHostApplication: authenticatedUser.has_pending_host_application,
          hasIncompleteListing: false,
          hasHostPayoutMethod: false,
        },
      });
    } catch (error) {
      const errorResponse = createAuthErrorResponse(error, 'Google');
      return res.status(500).json(errorResponse);
    }
  },
);

module.exports = googleAuthRouter;
