import UserModel from "../models/UserModel";
import { getStripe, stripeConfig } from "../config/stripe";

export type WalletStripeFlags = {
  stripeConnected: boolean;
  isStripeConnected: boolean;
  stripeChargesEnabled: boolean;
  stripeDetailsSubmitted: boolean;
  stripeStatus: "active" | "pending" | "connect_required";
};

export function walletStripeFlagsFromUser(doc: {
  stripeConnected?: boolean;
  stripeChargesEnabled?: boolean;
  stripeDetailsSubmitted?: boolean;
  stripeAccountId?: string | null;
}): WalletStripeFlags {
  const chargesEnabled = Boolean(doc.stripeChargesEnabled);
  const detailsSubmitted = Boolean(doc.stripeDetailsSubmitted);
  const hasAccount = Boolean(doc.stripeAccountId?.trim());
  const stripeStatus: WalletStripeFlags["stripeStatus"] = !hasAccount
    ? "connect_required"
    : chargesEnabled
      ? "active"
      : detailsSubmitted
        ? "pending"
        : "connect_required";

  return {
    stripeConnected: detailsSubmitted || chargesEnabled,
    isStripeConnected: chargesEnabled,
    stripeChargesEnabled: chargesEnabled,
    stripeDetailsSubmitted: detailsSubmitted,
    stripeStatus,
  };
}

/** Pull Connect account state from Stripe and persist on User (app wallet payouts). */
export async function syncWalletUserStripeStatus(
  userId: string,
): Promise<WalletStripeFlags> {
  if (!stripeConfig.secretKey) {
    throw new Error("Stripe is not configured");
  }
  const user = await UserModel.findById(userId);
  if (!user || user.isDeleted) {
    throw new Error("User not found");
  }
  if (!user.stripeAccountId) {
    return walletStripeFlagsFromUser(user);
  }

  const stripe = getStripe();
  const account = await stripe.accounts.retrieve(user.stripeAccountId);
  const detailsSubmitted = account.details_submitted ?? false;
  const chargesEnabled = account.charges_enabled ?? false;

  user.stripeDetailsSubmitted = detailsSubmitted;
  user.stripeChargesEnabled = chargesEnabled;
  user.stripeConnected = detailsSubmitted;
  await user.save();

  return walletStripeFlagsFromUser(user);
}

/** Best-effort sync on login / profile read (no throw). */
export async function trySyncWalletUserStripeStatus(userId: string): Promise<void> {
  if (!stripeConfig.secretKey) return;
  const linked = await UserModel.findById(userId)
    .select("stripeAccountId isDeleted")
    .lean();
  if (!linked || linked.isDeleted || !linked.stripeAccountId) return;
  try {
    await syncWalletUserStripeStatus(userId);
  } catch (err) {
    console.warn(
      "[wallet] Stripe Connect sync on read failed:",
      err instanceof Error ? err.message : err,
    );
  }
}
