import * as functions from "firebase-functions";
import { userWalletCol, userWalletHistoryCol } from "./collections";
import { CustomError } from "./utils/custom_error";
import { UserWalletHistory, UserWalletModel } from "./model/user_wallet_model";

export const requestCreateWallet = functions.https.onCall(
  async (data, context) => {
    try {
      // Check if user is authenticated
      if (!context.auth) {
        throw new CustomError("unauthenticated", "User must be authenticated");
      }

      const userId = context.auth.uid;

      // Check if wallet already exists by trying to get it
      const userWalletRef = userWalletCol.doc(userId);
      const userWallet = await userWalletRef.get();

      if (userWallet.exists) {
        return { success: false, message: "User wallet already exists" };
      }

      // Create wallet since it doesn't exist
      await createWalletDataForUser(userId);

      return { success: true, message: "Wallet created successfully" };
    } catch (error) {
      throw error;
    }
  }
);
/**
 * Retrieves a user's wallet information from the database
 * @param userId - The ID of the user whose wallet to retrieve
 * @returns Promise<UserWalletModel> - The user's wallet information
 * @throws CustomError if wallet is not found or on database errors
 */
export const getUserWallet = async (
  userId: string
): Promise<UserWalletModel> => {
  try {
    const walletRef = userWalletCol.doc(userId);
    const walletDoc = await walletRef.get();

    if (!walletDoc.exists) {
      throw new CustomError(
        "not-found",
        `Wallet not found for user: ${userId}`
      );
    }

    return walletDoc.data() as UserWalletModel;
  } catch (error) {
    if (error instanceof CustomError) {
      throw error;
    }
    // Cast error to any to safely access message property
    const errorMessage = (error as any)?.message || "Unknown error occurred";
    throw new CustomError(
      "internal",
      `Error retrieving wallet for user ${userId}: ${errorMessage}`
    );
  }
};

export const createWalletDataForUser = async (userId: string) => {
  try {
    const userWalletCheckRef = userWalletCol.doc(userId);
    const userWalletCheck = await userWalletCheckRef.get();
    if (userWalletCheck.exists) {
      throw new CustomError("already-exists", "user wallet already exists");
    }
    const newUserWallet: UserWalletModel = {
      id: userId,
      balance: 0,
      updatedAt: new Date(),
      userId: userId,
    };
    await userWalletCol.doc(userId).set(newUserWallet);
  } catch (error) {
    throw error;
  }
};

export const addHistoryWalletUser = async (
  walletId: string,
  history: UserWalletHistory
) => {
  try {
    await userWalletHistoryCol(walletId).add(history);
  } catch (error) {
    throw error;
  }
};

/**
 * Resets a user's wallet balance to 0
 * @param userId - The ID of the user whose wallet balance to reset
 * @throws CustomError if wallet is not found or on database errors
 */
export const resetWalletBalance = async (userId: string): Promise<void> => {
  try {
    const walletRef = userWalletCol.doc(userId);
    const walletDoc = await walletRef.get();

    if (!walletDoc.exists) {
      throw new CustomError(
        "not-found",
        `Wallet not found for user: ${userId}`
      );
    }

    await walletRef.update({
      balance: 0,
      updatedAt: new Date(),
    });
  } catch (error) {
    // Cast error to any to safely access message property
    const errorMessage = (error as any)?.message || "Unknown error occurred";
    throw new CustomError(
      "internal",
      `Error resetting wallet balance for user ${userId}: ${errorMessage}`
    );
  }
};

/**
 * Increases a user's wallet balance by the specified amount
 * @param userId - The ID of the user whose wallet balance to increase
 * @param amount - The amount to increase the balance by
 * @throws CustomError if wallet is not found or on database errors
 */
export const increaseWalletBalance = async (
  userId: string,
  amount: number
): Promise<void> => {
  try {
    const walletRef = userWalletCol.doc(userId);
    const walletDoc = await walletRef.get();

    if (!walletDoc.exists) {
      throw new CustomError(
        "not-found",
        `Wallet not found for user: ${userId}`
      );
    }

    const currentBalance = walletDoc.data()?.balance || 0;
    const newBalance = currentBalance + amount;

    await walletRef.update({
      balance: newBalance,
      updatedAt: new Date(),
    });

    // Add transaction to wallet history
    await addHistoryWalletUser(userId, {
      initialAmount: currentBalance,
      finalAmount: newBalance,
      transactionAmount: amount,
      createdAt: new Date(),
      userId: userId,
      status: "success",
      description: "Consultation payment received",
      type: "Payment",
    });
  } catch (error) {
    const errorMessage = (error as any)?.message || "Unknown error occurred";
    throw new CustomError(
      "internal",
      `Error increasing wallet balance for user ${userId}: ${errorMessage}`
    );
  }
};
