import db from "../models/index.js";
import PsbService from "../thirdParties/psbService.js";

/**
 * READ-ONLY diagnostic script.
 * Finds every locally "failed" payout transaction, requeries each one against
 * 9PSB directly, and reports any that 9PSB says actually succeeded.
 *
 * This script never writes to the database — it only reads Transactions and
 * calls out to 9PSB. Reconciling any mismatches found here is a separate,
 * deliberate step left to a human (or a follow-up script) to decide on.
 *
 * Usage: node src/scripts/requeryFailedTransactions.js
 */

const { Transaction } = db;
const DELAY_BETWEEN_REQUERIES_MS = 400; // be polite to 9PSB's API

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function run() {
  console.log("🔍 Requery Failed Transactions — READ ONLY (no database writes will be made)\n");

  const failedTxs = await Transaction.findAll({
    where: { status: "failed", class: "payout" },
    order: [["createdAt", "DESC"]],
  });

  if (failedTxs.length === 0) {
    console.log("No failed payout transactions found. Nothing to check.");
    return;
  }

  console.log(`Found ${failedTxs.length} failed payout transaction(s). Requerying each against 9PSB...\n`);

  const mismatches = [];   // local: failed, 9PSB: actually successful
  const confirmedFailed = []; // local: failed, 9PSB: confirms failed
  const unclear = [];      // couldn't get a clean answer

  for (const tx of failedTxs) {
    const payload = {
      transactionId: tx.transaction_id,
      amount: Math.round(parseFloat(tx.amount)),
      transactionType: "OTHER_BANKS",
      transactionDate: tx.createdAt.toISOString().split("T")[0],
      accountNo: "",
    };

    try {
      const result = await PsbService.walletRequery(payload, "AIRPERO");
      const psbStatus = result?.status;

      console.log(`- ${tx.transaction_id} | local: failed | 9PSB status: ${psbStatus || "unknown"}`);

      if (psbStatus === "SUCCESS") {
        mismatches.push({
          transaction_id: tx.transaction_id,
          amount: tx.amount,
          merchantId: tx.merchantId,
          customerId: tx.customerId,
          createdAt: tx.createdAt,
          psbResponse: result,
        });
      } else if (psbStatus === "FAILED") {
        confirmedFailed.push(tx.transaction_id);
      } else {
        unclear.push({ transaction_id: tx.transaction_id, psbResponse: result });
      }
    } catch (err) {
      console.error(`  ⚠️ Requery call failed for ${tx.transaction_id}: ${err.response?.data ? JSON.stringify(err.response.data) : err.message}`);
      unclear.push({ transaction_id: tx.transaction_id, error: err.message });
    }

    await sleep(DELAY_BETWEEN_REQUERIES_MS);
  }

  console.log("\n================ SUMMARY ================");
  console.log(`Total failed payout transactions checked: ${failedTxs.length}`);
  console.log(`Confirmed still failed on 9PSB's side:     ${confirmedFailed.length}`);
  console.log(`No clear answer from 9PSB:                 ${unclear.length}`);
  console.log(`Marked failed locally but ACTUALLY SUCCESSFUL on 9PSB: ${mismatches.length}`);

  if (mismatches.length > 0) {
    console.log("\n⚠️  MISMATCHES — these need manual reconciliation:");
    mismatches.forEach((m) => {
      console.log(
        `  - transaction_id: ${m.transaction_id} | amount: ${m.amount} | merchantId: ${m.merchantId} | customerId: ${m.customerId || "N/A"} | createdAt: ${m.createdAt.toISOString()}`
      );
    });
  }

  if (unclear.length > 0) {
    console.log("\nℹ️  Unclear responses (review manually):");
    unclear.forEach((u) => {
      console.log(`  - transaction_id: ${u.transaction_id} | ${u.error ? `error: ${u.error}` : `raw: ${JSON.stringify(u.psbResponse)}`}`);
    });
  }

  console.log("\n===========================================");
  console.log("No database changes were made — this script is strictly read-only.");
}

run()
  .catch((err) => {
    console.error("❌ Script error:", err);
    process.exitCode = 1;
  })
  .finally(() => {
    db.sequelize.close();
  });
