import moment from "moment";
import CONSTANTS from "../config/constants";
import log from "../config/log";
import payoutTransactionDB from "../models/payoutTransaction.model";
import walletDB from "../models/wallet.model";

export const recordTransferInitiate = async ({
  clientId,
  userType,
  staffId,
  transferAmount,
}: {
  clientId: number;
  userType: number;
  staffId: number | null;
  transferAmount: number;
}) => {
  const C = "Wallet Helper";
  const F = "recordTransferInitiate";
  try {
    log.info(
      `[${C}], [${F}], Client Id [${clientId}], User Type [${userType}], Staff Id [${staffId}], Transfer Amount [${transferAmount}]`,
    );

    const clientWallet = await walletDB.getByClientId({ clientId });

    const staffWallet = await walletDB.getByClientIdAndStaffId({
      clientId,
      staffId,
    });

    const wallet = userType === CONSTANTS.USER_TYPE.STAFF ? staffWallet : clientWallet;

    if (!wallet) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}], UserType [${userType}], Wallet Not Found, Skipping Handling In Kipinn Wallet`,
      );

      return false;
    }

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}], UserType [${userType}], Wallet Amount [${wallet?.amount}], Wallet Balance [${wallet.balance}], Transfer Amount [${transferAmount}]`,
    );

    if (Number(wallet.balance) < Number(transferAmount)) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}], UserType [${userType}], Wallet Balance [${wallet.balance}], Transfer Amount [${transferAmount}], Insufficient Balance, Skipping Handling In Kipinn Wallet`,
      );

      return false;
    }

    await walletDB.updateAmount({
      clientId,
      staffId: userType === CONSTANTS.USER_TYPE.STAFF ? staffId : null,
      amount: Number((Number(wallet.amount) - Number(transferAmount)).toFixed(2)),
    });

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
        //Amount should also be subtracted from main client wallet when staff is paying
      await walletDB.updateAmount({
        clientId,
        staffId: null,
        amount: Number((Number(clientWallet?.amount) - Number(transferAmount)).toFixed(2)),
      });
    }

    await walletDB.updateBalance({
      clientId,
      staffId: userType === CONSTANTS.USER_TYPE.STAFF ? staffId : null,
      balance: Number((Number(wallet.balance) - Number(transferAmount)).toFixed(2)),
    });

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}], UserType [${userType}], Kipinn Wallet Amount Deducted Successfully`,
    );

    return true;
  } catch (error: any) {
    log.info(`[${C}], [${F}], Client Id [${clientId}], Error [${error}]`);
    return false;
  }
};

export const handleTransferFail = async ({
  clientId,
  userType,
  staffId,
  transferAmount,
}: {
  clientId: number;
  userType: number;
  staffId: number | null;
  transferAmount: number;
}) => {
  const C = "Wallet Helper";
  const F = "handleTransferFail";
  try {
    log.info(
      `[${C}], [${F}], Client Id [${clientId}], User Type [${userType}], Staff Id [${staffId}], Transfer Amount [${transferAmount}] Adding The Deducted Amount Back To Wallet`,
    );

    const clientWallet = await walletDB.getByClientId({ clientId });

    const staffWallet = await walletDB.getByClientIdAndStaffId({
      clientId,
      staffId,
    });

    const wallet = userType === CONSTANTS.USER_TYPE.STAFF ? staffWallet : clientWallet;

    if (!wallet) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}], UserType [${userType}], Wallet Not Found, Skipping Handling In Kipinn Wallet`,
      );

      return false;
    }

    // if (Number(wallet.balance) < Number(transferAmount)) {
    //   log.info(
    //     `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}], UserType [${userType}], Insufficient Balance, Skipping Handling In Kipinn Wallet`,
    //   );

    //   return false;
    // }

    await walletDB.updateAmount({
      clientId,
      staffId: userType === CONSTANTS.USER_TYPE.STAFF ? staffId : null,
      amount: Number((Number(wallet.amount) + Number(transferAmount)).toFixed(2)),
    });

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
        //Amount should also be added back to main client wallet when staff paid to failed
      await walletDB.updateAmount({
        clientId,
        staffId: null,
        amount: Number((Number(clientWallet?.amount) + Number(transferAmount)).toFixed(2)),
      });
    }

    await walletDB.updateBalance({
      clientId,
      staffId: userType === CONSTANTS.USER_TYPE.STAFF ? staffId : null,
      balance: Number((Number(wallet.balance) + Number(transferAmount)).toFixed(2)),
    });

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}], UserType [${userType}], Deducted Amount Added Back To Kipinn Wallet Successfully`,
    );

    return true;
  } catch (error: any) {
    log.info(`[${C}], [${F}], Client Id [${clientId}], Error [${error}]`);
    return false;
  }
};

export const handleRecharge = async ({
  subWalletId,
  rechargeAmount,
}: {
  subWalletId: string;
  rechargeAmount: number;
}) => {
  const C = "Wallet Helper";
  const F = "handleRecharge";
  try {
    log.info(
      `[${C}], [${F}], Sub Wallet Id [${subWalletId}], Recharge Amount [${rechargeAmount}], Adding Recharge`,
    );

    const wallet = await walletDB.getBySubWalletId({
      subWalletId,
    });

    if (!wallet) {
      log.info(
        `[${C}], [${F}], Sub Wallet Id [${subWalletId}], Wallet Not Found, Skipping Handling In Kipinn Wallet`,
      );

      return false;
    }

    log.info(`[${C}], [${F}], Client Id [${wallet?.clientId}], Wallet Amount [${wallet.amount}], Wallet Balance [${wallet?.balance}], Recharge Amount [${rechargeAmount}]`);

    await walletDB.updateAmount({
      clientId: wallet?.clientId,
      staffId: null,
      amount: Number((Number(wallet.amount) + Number(rechargeAmount)).toFixed(2)),
    });

    await walletDB.updateBalance({
      clientId: wallet?.clientId,
      staffId: null,
      balance: Number((Number(wallet.balance) + Number(rechargeAmount)).toFixed(2)),
    });

    log.info(
      `[${C}], [${F}], Client Id [${wallet.clientId}], Sub Wallet Id [${subWalletId}], Recharge Amount [${rechargeAmount}], Added Successfully`,
    );

    return true;
  } catch (error: any) {
    log.info(
      `[${C}], [${F}], Sub Wallet Id [${subWalletId}], Error [${error}]`,
    );
    return false;
  }
};

export const getWalletBalanceAndLimits = async ({
  clientId,
  userType,
  staffId,
}: {
  clientId: number;
  userType: number;
  staffId: number | null;
}) => {
  const C = "Wallet Helper";
  const F = "getWalletBalanceAndLimits";
  try {
    log.info(
      `[${C}], [${F}], Client Id [${clientId}], User Type [${userType}], Staff Id [${staffId}], Getting Wallet Balance And Limits`,
    );

    const clientWallet = await walletDB.getByClientId({ clientId });

    const staffWallet = await walletDB.getByClientIdAndStaffId({
      clientId,
      staffId,
    });

    const wallet = userType === CONSTANTS.USER_TYPE.STAFF ? staffWallet : clientWallet;

    let dailyPayoutLimitRemaining = null;

    if (!wallet) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}], UserType [${userType}], Wallet Not Found`,
      );

      return {
        walletBalance: 0,
        maxTransLimit: 0,
        dailyPayoutLimit: 0,
        dailyPayoutLimitRemaining: 0,
      };
    }

    if(userType === CONSTANTS.USER_TYPE.STAFF) {
      const todayTransferAmount = await payoutTransactionDB.getByDoneByIdAndDoneByTypeAndDate({
        clientId,
        doneById: Number(userType) === CONSTANTS.USER_TYPE.STAFF ? staffId : clientId,
        doneByType: userType,
        startDate: moment().format("YYYY-MM-DD"),
        endDate: moment().format("YYYY-MM-DD"),
      });

      dailyPayoutLimitRemaining = Number((Number(staffWallet?.dailyPayoutLimit) - Number(todayTransferAmount)).toFixed(2)); 
    }

    return {
      walletBalance: Number(wallet.balance),
      maxTransLimit: Number(wallet.maxTransLimit),
      dailyPayoutLimit: Number(wallet.dailyPayoutLimit),
      dailyPayoutLimitRemaining: dailyPayoutLimitRemaining,
    };
  } catch (error: any) {
    log.info(`[${C}], [${F}], Client Id [${clientId}], Error [${error}]`);
    return {
      walletBalance: 0,
      maxTransLimit: 0,
      dailyPayoutLimit: 0,
      dailyPayoutLimitRemaining: 0,
    };
  }
};
