import Transaction, { ITransaction } from "@/models/transactions";
import { User } from "@/models/user";
import dbConnect from "@/lib/connectdb";

interface CreateTransactionParams {
  userEmail: string;
  type: string;
  amount: number;
  referenceId: string;
  userId: string;
  refund?: boolean;
  // Optional fields
  iucOrSmartcardNumber?: number;
  cableId?: number;
  cablePlanId?: number;
  meterNumber?: number;
  token?: string;
  customerPhone?: number;
  meterType?: string;
  customerName?: string;
  customerAddress?: string;
  planType?: string;
  discoName: string;
  dataType?: string;
  mobileNumber?: number;
  medium?: string;
  portedNumber?: boolean;
  networkId?: number;
  airtimeType?: string;
  buyingPrice?: number;
  planId?: number;
  fundingType?: "Manual" | "Automatic";
  fundingSource?: "API" | "Admin" | "Referral" | "ONE TIME PAYMENT";
}

export async function createTransaction(
  params: CreateTransactionParams
): Promise<ITransaction> {
  const {
    userId,
    userEmail,
    type,
    amount,
    referenceId,
    refund,
    ...otherFields
  } = params;

  await dbConnect();

  const user = await User.findById(userId);
  if (!user) {
    throw new Error("User not found");
  }
  if (amount <= 0) {
    throw new Error("Invalid amount. Must be greater than 0.");
  }

  const balanceBefore = user.accountBalance;
  let balanceAfter = balanceBefore;

  // Debit immediately for purchases (non-funding transactions)
  if (type === "ManualFunding" || type === "AutomaticFunding") {
    balanceAfter = balanceBefore + amount;
    user.accountBalance = balanceAfter;
  } else {
    // Purchases (airtime, data, bills, etc.)
    if (balanceBefore < amount) {
      throw new Error("Insufficient balance");
    }
    balanceAfter = balanceBefore - amount;
    user.accountBalance = balanceAfter;
  }

  const transactionData = {
    userId,
    userEmail,
    type,
    amount,
    referenceId,
    refund: refund || false,
    status: "Pending",
    balanceBefore,
    balanceAfter,
    ...otherFields,
  };

  const transaction = new Transaction(transactionData);
  await transaction.save();
  await user.save(); // apply debit/credit immediately

  return transaction;
}

// export async function updateTransactionStatus(
//   referenceId: string,
//   type: string,
//   status: string,
//   amount: number,
//   token: string
// ): Promise<ITransaction> {
//   await dbConnect();
//   const transaction = await Transaction.findOne({ referenceId });
//   if (!transaction) {
//     throw new Error("Transaction not found");
//   }

//   const user = await User.findById(transaction.userId);
//   if (!user) {
//     throw new Error("If the user exists, they will be handled accordingly.");
//   }
//   if (amount <= 0) {
//     throw new Error("Invalid amount. Must be greater than 0.");
//   }

//   if (status === "Successful") {
//     transaction.balanceAfter =
//       type === "ManualFunding" || type === "AutomaticFunding"
//         ? transaction.balanceBefore + amount
//         : transaction.balanceBefore - amount;
//     user.accountBalance = transaction.balanceAfter;
//   } else {
//     transaction.balanceAfter = transaction.balanceBefore;
//     transaction.refund = true;
//     user.accountBalance = transaction.balanceBefore;
//   }

//   transaction.status = status;
//   transaction.token = token;
//   await transaction.save();
//   await user.save();

//   return transaction;
// } **former working updateTransactionStatus
export async function updateTransactionStatus(
  referenceId: string,
  type: string,
  status: string,
  amount: number,
  token: string
): Promise<ITransaction> {
  await dbConnect();
  const transaction = await Transaction.findOne({ referenceId });
  if (!transaction) {
    throw new Error("Transaction not found");
  }

  const user = await User.findById(transaction.userId);
  if (!user) {
    throw new Error("User not found");
  }

  if (amount <= 0) {
    throw new Error("Invalid amount. Must be greater than 0.");
  }

  if (status === "Successful") {
    // ✅ nothing to do – user was already debited/credited in createTransaction
    transaction.balanceAfter = user.accountBalance;
  } else if (status === "Pending") {
    transaction.refund = false;
  } else {
    // ❌ refund if failed
    if (type !== "ManualFunding" && type !== "AutomaticFunding") {
      user.accountBalance = transaction.balanceBefore; // refund
      transaction.balanceAfter = transaction.balanceBefore;
      transaction.refund = true;
    }
  }

  transaction.status = status;
  transaction.token = token;
  await transaction.save();
  await user.save();

  return transaction;
}
