import { onRequest } from 'firebase-functions/v2/https';
import { logger } from 'firebase-functions/v2';

import { corsV2Origins, db } from '../config'; // Import corsV2Origins

// Other imports
import * as admin from 'firebase-admin';
import { toErrorWithMessage } from '../utils';

export const adminChangePasswordV2 = onRequest(
  {
    cors: corsV2Origins,
  },
  async (request, response) => {
    logger.info(
      'adminChangePassword: Function invoked (CORS handled by framework using config).',
    );

    const token = request.get('Authorization')?.split('Bearer ')[1];

    if (token == null) {
      logger.warn('adminChangePassword: No token provided.');
      response.status(401).send({
        error: 'unauthenticated',
        message: 'You must be logged in to change the password.',
      });
      return;
    }

    let decodedToken;
    try {
      decodedToken = await admin.auth().verifyIdToken(token);
      logger.info(
        `adminChangePassword: Token verified for admin UID: ${decodedToken.uid}`,
      );
    } catch (error: unknown) {
      const errorMsg = toErrorWithMessage(error).message;
      logger.error(
        `adminChangePassword: Token verification failed: ${errorMsg}`,
      );
      response.status(401).send({
        error: 'unauthenticated',
        message: 'Invalid token.',
        details: errorMsg,
      });
      return;
    }

    // Fetch the user's role using the authenticated user's UID
    let userRole = 0; // default
    try {
      const userDoc = await db.collection('users').doc(decodedToken.uid).get();

      if (userDoc.exists) {
        userRole = userDoc.data()?.role || 0;
        logger.info(
          `adminChangePassword: Requesting admin role is ${userRole}.`,
        );
      } else {
        logger.warn(
          `adminChangePassword: Admin user document not found for UID: ${decodedToken.uid}`,
        );
      }
    } catch (error: unknown) {
      const errorMsg = toErrorWithMessage(error).message;
      logger.error(
        `adminChangePassword: Failed to fetch admin role for UID ${decodedToken.uid}: ${errorMsg}`,
      );
      response.status(500).send({
        error: 'internal',
        message: "Failed to fetch user's role.",
        details: errorMsg,
      });
      return;
    }

    // --- Role Check ---
    const requiredRole = 5; // Define required role level
    if (userRole < requiredRole) {
      logger.warn(
        `adminChangePassword: Permission denied for admin UID ${decodedToken.uid} with role ${userRole}. Required: ${requiredRole}`,
      );
      response.status(403).send({
        error: 'permission-denied',
        message: 'Insufficient role level to change the password.',
      });
      return;
    }
    logger.info(
      `adminChangePassword: Permission granted for admin UID ${decodedToken.uid}.`,
    );

    // --- Proceed with password change ---
    try {
      const { email, newPassword } = request.body;
      if (!email || !newPassword) {
        logger.warn(
          'adminChangePassword: Missing email or newPassword in request body.',
        );
        response.status(400).send({
          error: 'bad-input',
          message: 'Both email and newPassword are required.',
        });
        return;
      }

      logger.info(
        `adminChangePassword: Attempting to change password for email: ${email}`,
      );
      const userRecord = await admin.auth().getUserByEmail(email);

      await admin.auth().updateUser(userRecord.uid, {
        password: newPassword,
      });
      logger.info(
        `adminChangePassword: Successfully changed password for user UID: ${userRecord.uid}`,
      );

      response.send({ success: true, uid: userRecord.uid });
    } catch (error: unknown) {
      const errorMsg = toErrorWithMessage(error).message;
      if (
        error instanceof Error &&
        'code' in error &&
        error.code === 'auth/user-not-found'
      ) {
        logger.warn(
          `adminChangePassword: User not found for email: ${request.body?.email}`,
        );
        response.status(404).send({
          error: 'not-found',
          message: 'No user associated with this email.',
          details: errorMsg,
        });
      } else {
        logger.error(
          `adminChangePassword: Failed to change password: ${errorMsg}`,
          { error },
        );
        response.status(500).send({
          error: 'internal',
          message: 'Failed to change password.',
          details: errorMsg,
        });
      }
    }
  }, // End of the async handler function
); // End of onRequest
