import { Response } from "express";
import log from "../config/log";
import CONSTANTS from "../config/constants";
import propertyDB from "../models/property.model";
import CustomRequest from "../types/requestType";
import clientDB from "../models/client.model";
import bankDB from "../models/bank.model";
import staffDB from "../models/staff.model";
import propertiesTypes from "../schemas/property.schema";
import { FieldAlreadyExistsError } from "pdf-lib";
import clientConfigDB from "../models/clientConfig.model";
import { logBankActivity } from "../utils/logActivity";
import axios from "axios";
import { generateCashfreeVendorId } from "../utils/helpers";

const banks: any = {};

banks.List = async (req: CustomRequest, res: Response) => {
  const C = "Bank Controller";
  const F = "List";

  try {
    const userType = req.userType;
    const { isOnline = 0 } = req.query;
    let clientId = req.id;
    let isCashfreeEnabled = false;

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      clientId = staff.clientId;

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], isOnline [${isOnline}], Staff Id [${req.id}], Staff Requested....`
      );
    } else {
      log.info(`[${C}], [${F}], Client Id [${clientId}], isOnline [${isOnline}], Client Requested....`);
    }

    const client = await clientDB.getById({ id: clientId });

    if (!client) {
      log.info(`[${C}], [${F}], Client Id [${clientId}], No Tenant Found`);
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }
    let banks = [];
    if (Number(isOnline) === 0) {
      banks = await bankDB.getByClientIdByOnlineSettlement({ clientId, isOnlineSettlement: Number(isOnline) });
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${req.id}], Offline bank account list sent successfully`
      );
    } else {
      banks = await bankDB.getByClientIdByOnlineSettlement({ clientId, isOnlineSettlement: Number(isOnline) });
      if (banks && banks.length > 0) {
        for (let bank of banks) {
          let properties = await propertyDB.getPropIdsByClientIdAndBankId({
            clientId,
            bankId: bank.id
          });
          bank.properties = properties || [];
          let isSettlement = false;
          if (properties) {
            isSettlement = true;
          }
          bank.isSettlement = isSettlement;
        }
      }
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${req.id}], Online bank account list sent successfully`
      );
    }

    if (Number(client.paymentGateway) === CONSTANTS.PAYMENT_GATEWAY.CASHFREE) {
      isCashfreeEnabled = true;
    } else {
      const cashfreeProperty = await propertyDB.getByClientIdAndPaymentGateway({
        clientId,
        paymentGateway: CONSTANTS.PAYMENT_GATEWAY.CASHFREE,
      });

      if (cashfreeProperty && cashfreeProperty.length > 0) isCashfreeEnabled = true;
    }
    

    // log.info(
    //   `[${C}], [${F}], Client Id [${clientId}], Staff Id [${req.id}], Bank account list sent successfully`
    // );

    return res.status(200).json({
      msg: `Bank account list sent successfully`,
      data: banks || [],
      isCashfreeEnabled,
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

banks.AddBank = async (req: CustomRequest, res: Response) => {
  const C = "Bank Controller";
  const F = "AddBank";

  try {
    let {
      holderName,
      accountNum,
      ifsc,
      bankAddress,
      type,
      upiId,
      bankName,
      properties,
    } = req.body;

    const userType = req.userType;

    let clientId = req.id;

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Holder Name [${holderName}], Account Number [${accountNum}], IFSC [${ifsc}], Bank Address [${bankAddress}], Type [${type}], UPI ID [${upiId}], Bank Name [${bankName}], Properties Length [${properties.length}], Staff Id [${req.id}], No Staff Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      clientId = staff.clientId;

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Account Number [${accountNum}], IFSC [${ifsc}], Bank Address [${bankAddress}], Type [${type}], UPI ID [${upiId}], Bank Name [${bankName}], Properties Length [${properties.length}], Staff Id [${req.id}], Staff Requested....`
      );
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Account Number [${accountNum}], IFSC [${ifsc}], Bank Address [${bankAddress}], Type [${type}], UPI ID [${upiId}], Bank Name [${bankName}], Properties Length [${properties.length}], Client Requested....`
      );
    }

    const client = await clientDB.getById({ id: clientId });

    if (!client) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    if (properties.length > 0) {
      for (const index in properties) {
        try {
          const propertyId = properties[index];
          const property = await propertyDB.getById({ id: propertyId });
          if (!property) {
            log.info(
              `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Property Id [${propertyId}], No Property Found`
            );

            properties = properties.filter((item: any) => item !== propertyId);
            continue;
          }

          if (property.bankId) {
            log.info(
              `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Property Id [${propertyId}], Bank already linked`
            );
            properties = properties.filter((item: any) => item !== propertyId);
            continue;
          }
        } catch (error: any) {
          log.info(
            `[${C}], [${F}], Error while checking bank: ${error?.message || error
            }`
          );
        }
      }

      if (properties.length === 0) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Bank already linked`
        );
        return res.status(400).json({
          msg: `Property is already linked with another bank`,
          isSuccess: false,
        });
      }
    }

    let bankId = null;

    if (type === CONSTANTS.BANK_TYPES.BANK) {
      if (accountNum.length < 6) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Invalid Account Number`
        );
        return res.status(400).json({
          msg: "Invalid Bank Account Number",
          isSuccess: false,
        });
      }

      const isAccountExists = await bankDB.getByAccNum({ accountNum, clientId });

      if (isAccountExists) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Bank account already exists with same account number`
        );
        return res.status(400).json({
          msg: "Bank account already exists with same account number",
          isSuccess: false,
        });
      }

      bankId = await bankDB.addBank({
        clientId,
        holderName,
        accountNum,
        ifsc,
        bankAddress,
        type,
        bankName,
      });

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Bank account added successfully`
      );
    } else {
      if (upiId.length < 6) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Invalid UPI ID`
        );
        return res.status(400).json({
          msg: "Invalid UPI ID",
          isSuccess: false,
        });
      }

      const isAccountExists = await bankDB.getByUPI({ upiId });

      if (isAccountExists) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Bank account already exists with same UPI Id`
        );
        return res.status(400).json({
          msg: "UPI account already exists with same UPI Id",
          isSuccess: false,
        });
      }

      bankId = await bankDB.addUPI({
        clientId,
        type,
        upiId,
      });

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], UPI added successfully`
      );
    }

    for (const index in properties) {
      try {
        const propertyId = properties[index];
        await propertyDB.updateBankId({ id: propertyId, bankId });
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Property Id [${propertyId}], Bank Linked Successfully`
        );
      } catch (error: any) {
        log.info(
          `[${C}], [${F}], Error while adding bank: ${error?.message || error}`
        );
      }
    }

    return res.status(200).json({
      msg: `${type === CONSTANTS.BANK_TYPES.BANK ? "Bank" : "UPI"
        } account added successfully`,
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

banks.AddBankCashfree = async (req: CustomRequest, res: Response) => {
  const C = "Bank Controller";
  const F = "AddBankCashfree";

  try {
    let {
      holderName,
      accountNum,
      ifsc,
      bankAddress,
      type,
      bankName,
      properties,
      email,
      mobile,
    } = req.body;

    const userType = req.userType;
    
    log.info(
      `[${C}], [${F}], Holder Name [${holderName}], Account Number [${accountNum}], IFSC [${ifsc}], Bank Address [${bankAddress}], Type [${type}], Bank Name [${bankName}], Properties Length [${properties.length}], Email [${email}], Mobile [${mobile}]`
    );

    let clientId = req.id;

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Holder Name [${holderName}], Account Number [${accountNum}], IFSC [${ifsc}], Bank Address [${bankAddress}], Type [${type}], Bank Name [${bankName}], Properties Length [${properties.length}], Staff Id [${req.id}], No Staff Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      clientId = staff.clientId;

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Account Number [${accountNum}], IFSC [${ifsc}], Bank Address [${bankAddress}], Type [${type}], Bank Name [${bankName}], Properties Length [${properties.length}], Staff Id [${req.id}], Staff Requested....`
      );
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Account Number [${accountNum}], IFSC [${ifsc}], Bank Address [${bankAddress}], Type [${type}], Bank Name [${bankName}], Properties Length [${properties.length}], Client Requested....`
      );
    }

    const client = await clientDB.getById({ id: clientId });

    if (!client) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    if (properties.length > 0) {
      for (const index in properties) {
        try {
          const propertyId = properties[index];
          const property = await propertyDB.getById({ id: propertyId });
          if (!property) {
            log.info(
              `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Property Id [${propertyId}], No Property Found`
            );

            properties = properties.filter((item: any) => item !== propertyId);
            continue;
          }

          if (property.bankId) {
            log.info(
              `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Property Id [${propertyId}], Bank already linked`
            );
            properties = properties.filter((item: any) => item !== propertyId);
            continue;
          }
        } catch (error: any) {
          log.info(
            `[${C}], [${F}], Error while checking bank: ${error?.message || error}`
          );
        }
      }

      if (properties.length === 0) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Bank already linked`
        );
        return res.status(400).json({
          msg: `Property is already linked with another bank`,
          isSuccess: false,
        });
      }
    }

    let bankId = null;

    if (accountNum.length < 6) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Invalid Account Number`
      );
      return res.status(400).json({
        msg: "Invalid Bank Account Number",
        isSuccess: false,
      });
    }

    const isAccountExists = await bankDB.getByAccNum({ accountNum, clientId });

    if (isAccountExists) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Bank account already exists with same account number`
      );
      return res.status(400).json({
        msg: "Bank account already exists with same account number",
        isSuccess: false,
      });
    }

    bankId = await bankDB.addBankOnline({
      clientId,
      holderName,
      accountNum,
      ifsc,
      bankAddress,
      type,
      bankName,
      isOnlineSettlement: 1,
    });

    let xClientId = process.env.CASHFREE_CLIENTID;
    let xSecretKey = process.env.CASHFREE_SECRET;

    const isXClientId = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.CASHFREE,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.CASHFREE.X_CLIENT_ID,
    });
    const isXClientSecretKey = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.CASHFREE,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.CASHFREE.X_SECRET_KEY,
    });

    if (isXClientId && isXClientId.value && isXClientSecretKey && isXClientSecretKey.value) {
      xClientId = isXClientId.value;
      xSecretKey = isXClientSecretKey.value;
      log.info(`[${C}], [${F}], Client Id [${clientId}], X Client Id [${xClientId}], Secret Key [${xSecretKey}], Client Gateway `);
    } else {
      log.info(`[${C}], [${F}], Client Id [${clientId}], X Client Id [${xClientId}], Secret Key [${xSecretKey}], Kipinn Gateway `);
    }

    const vendorId = await generateCashfreeVendorId({
      holderName: holderName,
      bankName: bankName,
    });

    log.info(`[${C}], [${F}], Vendor Id [${vendorId}]`);

    // const options = {
    //   method: 'POST',
    //   headers: {
    //     'x-api-version': '2025-01-01',
    //     'x-client-id': xClientId,
    //     'x-client-secret': xSecretKey,
    //     'Content-Type': 'application/json'
    //   },
    //   body: {
    //     vendor_id: vendorId,
    //     status: 'ACTIVE',
    //     name: holderName,
    //     email: email,
    //     phone: mobile,
    //     verify_account: true,
    //     dashboard_access: true,
    //     schedule_option: 1,
    //     bank: {
    //       account_number: accountNum, 
    //       account_holder: holderName, 
    //       ifsc: ifsc
    //     },
    //     kyc_details: {
    //       // account_type: 'BUSINESS',
    //       // business_type: 'NBFC',
    //       // uidai: 753624181019,
    //       // gst: '11AAAAA1111A1Z0',
    //       // cin: 'L00000Aa0000AaA000000',
    //       // pan: 'BIAPA2934N',
    //       // passport_number: 'L6892603'
    //     }
    //   }
    // };

    // const createVendorResponse = await axios.post(`${process.env.CASHFREE_API_BASE_URL}/pg/easy-split/vendors`, options);

    const vendorPayload = {
      vendor_id: vendorId,
      status: 'ACTIVE',
      name: holderName,
      email: email,
      phone: `${mobile}`,
      verify_account: true,
      dashboard_access: true,
      schedule_option: 1,
      bank: {
        account_number: accountNum, 
        account_holder: holderName, 
        ifsc: ifsc
      },
      kyc_details: {
        // account_type: 'Individual',
        business_type: 'NBFC',
        // uidai: 378063274467,
        // gst: '11AAAAA1111A1Z0',
        // cin: 'L00000Aa0000AaA000000',
        // pan: 'BIAPA2934N',
        // passport_number: 'L6892603'
      }
    };

    const config = {
      headers: {
        'x-api-version': '2025-01-01',
        'x-client-id': xClientId,
        'x-client-secret': xSecretKey,
        'Content-Type': 'application/json'
      }
    };

    const createVendorResponse = await axios.post(
      `${process.env.CASHFREE_API_BASE_URL}/pg/easy-split/vendors`, 
      vendorPayload, 
      config
    );

    log.info(`Reponse [${JSON.stringify(createVendorResponse)}]`);

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Bank account added successfully`
    );

    for (const index in properties) {
      try {
        const propertyId = properties[index];
        await propertyDB.updateBankId({ id: propertyId, bankId });
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Holder Name [${holderName}], Property Id [${propertyId}], Bank Linked Successfully`
        );
      } catch (error: any) {
        log.info(
          `[${C}], [${F}], Error while adding bank: ${error?.message || error}`
        );
      }
    }

    return res.status(200).json({
      msg: `${type === CONSTANTS.BANK_TYPES.BANK ? "Bank" : "UPI"
        } account added successfully`,
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error2: ${error}`);
    log.info(`[${C}], [${F}], Error2: ${error.stack}`);
    if (error.isAxiosError && error.response) {
      log.info(`[${C}], [${F}], Cashfree API Rejected Request: ${JSON.stringify(error.response.data)}`);
    }
    // log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

banks.RemoveBank = async (req: CustomRequest, res: Response) => {
  const C = "Bank Controller";
  const F = "RemoveBank";

  try {
    const { bankId } = req.body;

    const userType = req.userType;

    let clientId = req.id;

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Bank Id [${bankId}], Staff Id [${req.id}], No Staff Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      clientId = staff.clientId;

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Staff Id [${req.id}], Staff Requested....`
      );
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Client Requested....`
      );
    }

    const client = await clientDB.getById({ id: clientId });

    if (!client) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const isBankExists = await bankDB.getById({ id: bankId });
    if (!isBankExists) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], No Bank Found`
      );
      return res
        .status(400)
        .json({ msg: "No bank account found", isSuccess: false });
    }

    const isBankLinked = await propertyDB.getByBankId({ bankId });
    if (isBankLinked) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Bank linked with a property `
      );
      return res.status(400).json({
        msg: "Please unlink the bank account from the property first",
        isSuccess: false,
      });
    }

    await bankDB.removeBank({ id: bankId });

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Bank Removed Successfully`
    );

    return res.status(200).json({
      msg: "Bank has been removed successfully",
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

banks.toggleBank = async (req: CustomRequest, res: Response) => {
  const C = "Bank Controller";
  const F = "toggleBank";

  try {
    const { toggleValue, propId, bankId } = req.body;

    const userType = req.userType;

    let clientId = req.id;

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], Staff Id [${req.id}], No Staff Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      clientId = staff.clientId;

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], Staff Id [${req.id}], Staff Requested....`
      );
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], Client Requested....`
      );
    }

    const client = await clientDB.getById({ id: clientId });

    if (!client) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const property = await propertyDB.getById({ id: propId });
    if (!property) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}],  Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], No Property Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    if (toggleValue === CONSTANTS.TOGGLES.LINK) {
      const bank = await bankDB.getById({ id: bankId });
      if (!bank) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}],  Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], No Bank Found`
        );
        return res.status(400).json({ msg: "No Bank Found", isSuccess: false });
      }

      if (property.bankId) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}],  Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], Bank already linked`
        );
        return res
          .status(400)
          .json({ msg: "Bank already linked", isSuccess: false });
      }

      await propertyDB.updateBankId({ id: propId, bankId });
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}],  Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], Bank linked Successfully`
      );
    } else {
      await propertyDB.updateBankId({ id: propId, bankId: null });
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}],  Toggle Value [${toggleValue}], Property Id [${propId}], Bank Id [${bankId}], Bank unlinked Successfully`
      );
    }

    return res.status(200).json({
      msg: `Bank account ${toggleValue === CONSTANTS.TOGGLES.LINK ? "linked" : "unlinked"
        } successfully`,
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

banks.LinkedProperties = async (req: CustomRequest, res: Response) => {
  const C = "Bank Controller";
  const F = "LinkedProperties";

  try {
    const { bankId } = req.params;

    const userType = req.userType;

    let clientId = req.id;

    let properties = [];

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      const staffId = req.id;
      const staff = await staffDB.getById({ id: staffId });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Bank Id [${bankId}], Staff Id [${staffId}], No Staff Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      log.info(
        `[${C}], [${F}], Bank Id [${bankId}], Staff Id [${staffId}], Staff Requested....`
      );

      clientId = staff.clientId;

      let staffLinkedProps = await propertyDB.getPropsByStaffId({
        staffId,
      });

      if (!staffLinkedProps) staffLinkedProps = [];

      let allLinkedProperties = await propertyDB.getBankLinkedProps({
        bankId,
        clientId,
      });

      if (!allLinkedProperties) allLinkedProperties = [];

      properties = allLinkedProperties.filter((property: propertiesTypes) => {
        return staffLinkedProps.find(
          (prop: propertiesTypes) => property.id === prop.id
        );
      });
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Client Requested....`
      );

      const client = await clientDB.getById({ id: clientId });

      if (!client) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], No Client Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      properties = await propertyDB.getBankLinkedProps({
        bankId,
        clientId,
      });
    }

    log.info(
      `[${C}], [${F}], Bank Id [${bankId}], Bank linked properties sent successfully`
    );

    return res.status(200).json({
      msg: `Bank linked properties list`,
      data: properties,
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

banks.SetAccountForProperty = async (req: CustomRequest, res: Response) => {
  const C = "Bank Controller";
  const F = "SetAccountForProperty";

  try {
    const { propIds, bankId } = req.body;

    const userType = req.userType;

    let clientId = req.id;
    let oldBankId = 0;
    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Bank Id [${bankId}], Prop Ids [${propIds}], Staff Id [${req.id}], No Staff Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      clientId = staff.clientId;

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Prop Ids [${propIds}], Staff Id [${req.id}], Staff Requested....`
      );
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Prop Ids [${propIds}], Client Requested....`
      );
    }

    const client = await clientDB.getById({ id: clientId });

    if (!client) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Prop Ids [${propIds}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const bank = await bankDB.getById({ id: bankId });
    if (!bank) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Prop Ids [${propIds}], No Bank Found`
      );
      return res.status(400).json({ msg: "No Bank Found", isSuccess: false });
    }
    const propIdList = propIds.split(",");
    let bankUpdated = false;
    let propertyNames = [];
    for (let propId of propIdList) {
      const property = await propertyDB.getById({ id: propId });
      if (!property) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Property Id [${propId}], No Property Found`
        );
        continue;
      }
      if (property.bankId && property.bankId === bankId) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Property Id [${propId}], Bank already linked`
        );
        return res.status(400).json({
          msg: "Bank already linked with this property",
          isSuccess: false,
        });
      }
      oldBankId = property?.bankId || 0;
      let paymentGateway = Number(client.paymentGateway);
      if (property?.paymentGateway && Number(property?.paymentGateway)) {
        paymentGateway = Number(property?.paymentGateway);
      }

      //if(Number(client.paymentGateway) === CONSTANTS.PAYMENT_GATEWAY.PAYU) {
      if (paymentGateway === CONSTANTS.PAYMENT_GATEWAY.PAYU) {
        //if (!childKey || !childMid) {
        if (!bank?.payuMid || !bank?.payuKey) {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Property Id [${propId}], PayU mId or key is MISSING`
          );
          return res.status(400).json({
            msg: "Please contact kipinn team",
            isSuccess: false,
          });
        }
        await propertyDB.updatePayuMidAnDKeyDetails({
          id: propId,
          payuMid: bank?.payuMid,
          payuKey: bank?.payuKey,
        });
        if (!bank?.easebuzzSubMerchantId) {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Property Id [${propId}], Easebuzz SubMerchantId is MISSING`
          );
          //continue;
        } else {
          let isSubAccountMidExist = await clientConfigDB.getClientConfigByPropId({
            clientId,
            provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.EASEBUZZ,
            type: CONSTANTS.CLIENT_CONFIG_TYPE.SUB_ACCOUNT_MID,
            propId,
          });
          if (!isSubAccountMidExist) {
            await clientConfigDB.create({
              clientId,
              provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.EASEBUZZ,
              type: CONSTANTS.CLIENT_CONFIG_TYPE.SUB_ACCOUNT_MID,
              value: bank?.easebuzzSubMerchantId,
              propId
            });
          }
        }

        //} else if(Number(client.paymentGateway) === CONSTANTS.PAYMENT_GATEWAY.EASEBUZZ) {
      } else if (paymentGateway === CONSTANTS.PAYMENT_GATEWAY.EASEBUZZ) {
        if (!bank?.easebuzzSubMerchantId) {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Property Id [${propId}], Easebuzz SubMerchantId is MISSING`
          );
          return res.status(400).json({
            msg: "Please contact kipinn team",
            isSuccess: false,
          });
        }
        let isSubAccountMidExist = await clientConfigDB.getClientConfigByPropId({
          clientId,
          provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.EASEBUZZ,
          type: CONSTANTS.CLIENT_CONFIG_TYPE.SUB_ACCOUNT_MID,
          propId,
        });
        if (!isSubAccountMidExist) {
          await clientConfigDB.create({
            clientId,
            provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.EASEBUZZ,
            type: CONSTANTS.CLIENT_CONFIG_TYPE.SUB_ACCOUNT_MID,
            value: bank?.easebuzzSubMerchantId,
            propId
          });
        } else {
          await clientConfigDB.update({
            clientId,
            provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.EASEBUZZ,
            type: CONSTANTS.CLIENT_CONFIG_TYPE.SUB_ACCOUNT_MID,
            value: bank?.easebuzzSubMerchantId,
            propId
          });
        }
        if (!bank?.payuMid || !bank?.payuKey) {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Property Id [${propId}], PayU mId or key is MISSING`
          );
        } else {
          await propertyDB.updatePayuMidAnDKeyDetails({
            id: propId,
            payuMid: bank?.payuMid,
            payuKey: bank?.payuKey,
          });
        }
        //} else if (Number(client.paymentGateway) === CONSTANTS.PAYMENT_GATEWAY.CASHFREE) {
      } else if (paymentGateway === CONSTANTS.PAYMENT_GATEWAY.CASHFREE) {
        if (!bank?.cashfreeVendorId) {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Bank Id [${bankId}], Property Id [${propId}], Cashfree Vendor Id is MISSING`
          );
          return res.status(400).json({
            msg: "Please contact kipinn team",
            isSuccess: false,
          });
        }
        let isVendorIdExist = await clientConfigDB.getClientConfigByPropId({
          clientId,
          provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.CASHFREE,
          type: CONSTANTS.CLIENT_CONFIG_TYPE.CASHFREE.VENDOR_ID,
          propId,
        });
        if (!isVendorIdExist) {
          await clientConfigDB.create({
            clientId,
            provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.CASHFREE,
            type: CONSTANTS.CLIENT_CONFIG_TYPE.CASHFREE.VENDOR_ID,
            value: bank?.cashfreeVendorId,
            propId
          });
        } else {
          await clientConfigDB.update({
            clientId,
            provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.CASHFREE,
            type: CONSTANTS.CLIENT_CONFIG_TYPE.CASHFREE.VENDOR_ID,
            value: bank?.cashfreeVendorId,
            propId
          });
        }
      }
      propertyNames.push(property?.name);

      bankUpdated = true;
      await propertyDB.updateBankId({ id: propId, bankId });
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}], Bank linked Successfully`
      );
    }

    if (bankUpdated) {
      let propNames = propertyNames.join(", ");
      await logBankActivity(
        req.userType!,
        Number(req.id)!,
        Number(req.parentClientId),
        Number(req.platform),
        CONSTANTS.ACTIVITY_TYPES.SWITCH_ONLINE_ACCOUNT,
        propNames,
        bankId,
        oldBankId,
      );
    }

    return res.status(200).json({
      msg: `Bank account ${bankUpdated === true ? "linked successfully" : "linking failed"
        }`,
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

export default banks;
