import { sendErrorResponse, sendSuccessResponse } from '../../utills/response';
import {
  createOrGetRecipientAccount,
  createQuote, createTransfer, getProfileId, fundTransfer
} from './wiseService';
import { Request, Response } from "express";
import { Transaction } from "../../database/transaction/transaction";
// import { Notification } from "../../database/notification/notification";
import { messages } from "../../utills/common";

async function sendMoney(requestBody: any) {
  try {
    // Step 1: Get Profile ID
    let profileId;
    try {
      profileId = await getProfileId();
    } catch (error: any) {
      throw new Error(error.message);
    }

    // Step 2: Create or Get Recipient Account
    let recipientAccountId;
    try {
      const recipientAccountData = {
        currency: 'USD',
        type: 'aba', // For US-based accounts
        details: {
          accountHolderName: requestBody.details.accountHolderName,
          accountType: 'CHECKING', // Account type: CHECKING or SAVINGS
          abartn: requestBody.details.abartn, // Mock ABA routing number
          accountNumber: requestBody.details.accountNumber, // Mock account number
          legalType: 'PRIVATE', // 'PRIVATE' or 'BUSINESS'
          address: {
            country: requestBody.details.address.country,
            city: requestBody.details.address.city,
            state: requestBody.details.address.state, // State (e.g., 'NY')
            postCode: requestBody.details.address.postCode,
            firstLine: requestBody.details.address.firstLine,
          },
        },
      };
      recipientAccountId = await createOrGetRecipientAccount(recipientAccountData);
    } catch (error: any) {
      throw new Error(error.message);
    }

    // Step 3: Create a Quote for the Transfer
    let quote;
    try {
      const quoteData = {
        sourceCurrency: 'USD',
        targetCurrency: 'USD',
        sourceAmount: requestBody.quoteData.sourceAmount, // Transfer amount
        rateType: 'FIXED',
      };
      quote = await createQuote(quoteData);
    } catch (error: any) {
      throw new Error(error.message);
    }

    // Step 4: Create the Money Transfer
    let transfer;
    try {
      transfer = await createTransfer(quote.id, recipientAccountId);
    } catch (error: any) {
      throw new Error(error.message);
    }

    // Step 5: Fund the Transfer
    let fund;
    try {
      fund = await fundTransfer(profileId, transfer.id);
    } catch (error: any) {
      throw new Error(error.message);
    }

    // Step 6: Update Transaction and Notify User
    try {
      const existingTransaction = await Transaction.findOne({ where: { id: requestBody.details.transactionId } });
      if (existingTransaction) {
        const allInvestments = await Transaction.createQueryBuilder("transaction")
          .where("transaction.userId = :userId", { userId: requestBody.details.userId })
          .getMany();

        const totalInvestedAmount = allInvestments.reduce((sum, investment) => sum + investment.depositAmount, 0);
        const totalWithdrawAmount = allInvestments.reduce((sum, investment) => sum + investment.withdrawAmount, 0);
        const remainingAmount = totalInvestedAmount - totalWithdrawAmount;

        existingTransaction.withdrawAmount = requestBody.quoteData.sourceAmount;
        existingTransaction.totalInvestedAmount = remainingAmount;
        existingTransaction.iswithdrawAmount = true; // Mark as withdrawal

        await existingTransaction.save();
      } else {
        throw new Error("Transaction not found");
      }
    } catch (error: any) {
      throw new Error(error.message);
    }

    console.log('Money transfer successful!');
    return fund;
  } catch (error: any) {
    console.error('Error in money transfer process:', error.message);
    throw error.message; // Rethrow the error for upstream handling
  }
}


export const transferMoney = async (req: Request, res: Response) => {
  try {
    console.log("transfer Money init.....")
    const data = await sendMoney(req.body);
    return sendSuccessResponse(res, 200, messages.withdrawSuccess, data);
  } catch (error: any) {
    return sendErrorResponse(res, 500, error);
  }
};


