/**
 * Smoke test for wallet Stripe Connect sync (app user payouts).
 *
 * Unit-tests flag derivation, then optionally hits Mongo + Stripe for a user
 * (default: mag@yopmail.com / acct_1TYsxHAc4NwIpYZR).
 *
 * Run: npx ts-node src/scripts/walletStripeSyncSmoke.ts
 *      WALLET_STRIPE_TEST_EMAIL=other@example.com npx ts-node src/scripts/walletStripeSyncSmoke.ts
 */

import dotenv from "dotenv";
import path from "path";

dotenv.config({ path: path.join(__dirname, "../config/.env") });

import mongoose from "mongoose";
import UserModel from "../models/UserModel";
import { getStripe, stripeConfig } from "../config/stripe";
import {
  syncWalletUserStripeStatus,
  walletStripeFlagsFromUser,
} from "../services/walletStripeSync";

let pass = 0;
let fail = 0;

function assert(condition: boolean, label: string, detail?: string) {
  if (condition) {
    pass++;
    console.log(`  PASS  ${label}`);
  } else {
    fail++;
    console.log(`  FAIL  ${label}`);
    if (detail) console.log(`        ${detail}`);
  }
}

function testFlagDerivation() {
  console.log("\n── Unit: walletStripeFlagsFromUser ──");

  const noAccount = walletStripeFlagsFromUser({});
  assert(noAccount.stripeStatus === "connect_required", "no account → connect_required");
  assert(!noAccount.isStripeConnected, "no account → isStripeConnected false");

  const pending = walletStripeFlagsFromUser({
    stripeAccountId: "acct_test",
    stripeDetailsSubmitted: true,
    stripeChargesEnabled: false,
  });
  assert(pending.stripeStatus === "pending", "details submitted, no charges → pending");
  assert(pending.stripeConnected === true, "stripeConnected true when details submitted");
  assert(!pending.isStripeConnected, "isStripeConnected false until charges enabled");

  const active = walletStripeFlagsFromUser({
    stripeAccountId: "acct_test",
    stripeDetailsSubmitted: true,
    stripeChargesEnabled: true,
  });
  assert(active.stripeStatus === "active", "charges enabled → active");
  assert(active.isStripeConnected === true, "isStripeConnected true when charges enabled");
}

async function testLiveSync() {
  const email = process.env.WALLET_STRIPE_TEST_EMAIL ?? "mag@yopmail.com";
  const dbUri = process.env.DB_URI;
  if (!dbUri) {
    console.log("\n── Live sync skipped (DB_URI not set) ──");
    return;
  }
  if (!stripeConfig.secretKey) {
    console.log("\n── Live sync skipped (STRIPE_SECRET_KEY not set) ──");
    return;
  }

  console.log(`\n── Live: sync user ${email} ──`);
  await mongoose.connect(dbUri);

  const before = await UserModel.findOne({ email }).lean();
  if (!before) {
    assert(false, `user ${email} exists in DB`);
    return;
  }

  console.log(`  userId: ${before._id}`);
  console.log(`  stripeAccountId (before): ${before.stripeAccountId ?? "(none)"}`);
  console.log(
    `  flags (before): connected=${before.stripeConnected} charges=${before.stripeChargesEnabled} details=${before.stripeDetailsSubmitted}`,
  );

  if (!before.stripeAccountId) {
    console.log("  (no stripeAccountId — skipping Stripe retrieve)");
    return;
  }

  const stripe = getStripe();
  const account = await stripe.accounts.retrieve(before.stripeAccountId);
  console.log(
    `  Stripe API: details_submitted=${account.details_submitted} charges_enabled=${account.charges_enabled}`,
  );

  const synced = await syncWalletUserStripeStatus(String(before._id));
  console.log(`  synced flags: ${JSON.stringify(synced)}`);

  assert(
    synced.stripeDetailsSubmitted === Boolean(account.details_submitted),
    "DB detailsSubmitted matches Stripe",
  );
  assert(
    synced.stripeChargesEnabled === Boolean(account.charges_enabled),
    "DB chargesEnabled matches Stripe",
  );
  assert(
    synced.isStripeConnected === Boolean(account.charges_enabled),
    "isStripeConnected matches charges_enabled",
  );

  if (account.charges_enabled) {
    assert(synced.stripeStatus === "active", "enabled account → stripeStatus active");
  } else if (account.details_submitted) {
    assert(synced.stripeStatus === "pending", "submitted but not enabled → pending");
  }
}

async function main() {
  testFlagDerivation();
  await testLiveSync();

  console.log("\n────────────────────────────────────");
  console.log(`Results: ${pass} passed, ${fail} failed`);
  console.log("────────────────────────────────────");

  await mongoose.disconnect().catch(() => undefined);
  process.exit(fail > 0 ? 1 : 0);
}

main().catch((err) => {
  console.error(err);
  mongoose.disconnect().catch(() => undefined);
  process.exit(1);
});
