/**
 * stripe-bootstrap.ts — crée les produits/prix Stripe TEST par lookup keys.
 *
 * Idempotent : liste d'abord les prix existants par lookup_key, ne crée que
 * les manquants. Re-run = no-op (tout en `exists`).
 *
 * Usage:
 *   bun --env-file=/path/to/.env.local run scripts/stripe-bootstrap.ts
 */
import Stripe from "stripe";

type PlanRow = {
  lookupKey: string;
  productName: string;
  unitAmount: number; // cents USD (et EUR, parité nominale)
  /** Absent = prix one-time (pas de `recurring`). */
  interval?: "month" | "year";
};

const PLANS: PlanRow[] = [
  {
    lookupKey: "solo_monthly",
    productName: "SEO Insight Solo",
    unitAmount: 999,
    interval: "month",
  },
  {
    lookupKey: "solo_annual",
    productName: "SEO Insight Solo",
    unitAmount: 9588,
    interval: "year",
  },
  {
    lookupKey: "starter_monthly",
    productName: "SEO Insight Starter",
    unitAmount: 4900,
    interval: "month",
  },
  {
    lookupKey: "starter_annual",
    productName: "SEO Insight Starter",
    unitAmount: 46800,
    interval: "year",
  },
  {
    lookupKey: "pro_monthly",
    productName: "SEO Insight Pro",
    unitAmount: 12900,
    interval: "month",
  },
  {
    lookupKey: "pro_annual",
    productName: "SEO Insight Pro",
    unitAmount: 118800,
    interval: "year",
  },
  {
    lookupKey: "agency_monthly",
    productName: "SEO Insight Agency",
    unitAmount: 29900,
    interval: "month",
  },
  {
    lookupKey: "agency_annual",
    productName: "SEO Insight Agency",
    unitAmount: 286800,
    interval: "year",
  },
  {
    lookupKey: "seat_monthly",
    productName: "SEO Insight Seat",
    unitAmount: 1900,
    interval: "month",
  },
  {
    lookupKey: "seat_annual",
    productName: "SEO Insight Seat",
    unitAmount: 18240,
    interval: "year",
  },
  // Credit pack — ONE-TIME purchase (25 $ / 25 000 requêtes MCP), no recurring.
  {
    lookupKey: "pack_mcp_25k",
    productName: "SEO Insight MCP Pack",
    unitAmount: 2500,
  },
  // SE-Ranking sync top-up — ONE-TIME purchase (9.99 $ / 100 syncs), no recurring.
  {
    lookupKey: "seranking_pack_100",
    productName: "SEO Insight SE-Ranking Syncs",
    unitAmount: 999,
  },
  // SE-Ranking BYO-key add-on — recurring monthly (9.99 $/mois).
  {
    lookupKey: "addon_seranking_byok",
    productName: "SEO Insight SE-Ranking BYO Key",
    unitAmount: 999,
    interval: "month",
  },
];

async function main() {
  const key = process.env.STRIPE_SECRET_KEY;
  if (!key) {
    console.error("ERROR: STRIPE_SECRET_KEY is not set.");
    process.exit(1);
  }
  // SAFETY: never create objects on a live key.
  if (!key.startsWith("sk_test_")) {
    console.error(
      "ERROR: STRIPE_SECRET_KEY is not a TEST key (must start with sk_test_). Aborting.",
    );
    process.exit(1);
  }

  const stripe = new Stripe(key);

  // 1. Existing prices by lookup_key (the API caps `lookup_keys` at 10 → chunk).
  const priceByLookupKey = new Map<string, Stripe.Price>();
  const allKeys = PLANS.map((p) => p.lookupKey);
  for (let i = 0; i < allKeys.length; i += 10) {
    const existing = await stripe.prices.list({
      lookup_keys: allKeys.slice(i, i + 10),
      limit: 100,
    });
    for (const price of existing.data) {
      if (price.lookup_key) priceByLookupKey.set(price.lookup_key, price);
    }
  }

  // 2. Resolve products: reuse the product of an existing sibling price when
  //    present, otherwise create one product per distinct product name.
  const productIdByName = new Map<string, string>();
  for (const plan of PLANS) {
    const existingPrice = priceByLookupKey.get(plan.lookupKey);
    if (existingPrice && !productIdByName.has(plan.productName)) {
      const productId =
        typeof existingPrice.product === "string"
          ? existingPrice.product
          : existingPrice.product.id;
      productIdByName.set(plan.productName, productId);
    }
  }
  for (const name of new Set(PLANS.map((p) => p.productName))) {
    if (productIdByName.has(name)) continue;
    const product = await stripe.products.create({ name });
    productIdByName.set(name, product.id);
    console.log(`product created: ${name} → ${product.id}`);
  }

  // 3. Create only the missing prices.
  const results: {
    lookupKey: string;
    priceId: string;
    status: "created" | "exists";
  }[] = [];
  for (const plan of PLANS) {
    const existingPrice = priceByLookupKey.get(plan.lookupKey);
    if (existingPrice) {
      results.push({
        lookupKey: plan.lookupKey,
        priceId: existingPrice.id,
        status: "exists",
      });
      continue;
    }
    const price = await stripe.prices.create({
      product: productIdByName.get(plan.productName)!,
      currency: "usd",
      unit_amount: plan.unitAmount,
      currency_options: { eur: { unit_amount: plan.unitAmount } },
      ...(plan.interval ? { recurring: { interval: plan.interval } } : {}),
      lookup_key: plan.lookupKey,
      transfer_lookup_key: true,
    });
    results.push({
      lookupKey: plan.lookupKey,
      priceId: price.id,
      status: "created",
    });
  }

  // 4. Clean table output.
  const keyWidth = Math.max(...results.map((r) => r.lookupKey.length));
  const idWidth = Math.max(...results.map((r) => r.priceId.length));
  console.log("");
  for (const r of results) {
    console.log(
      `${r.lookupKey.padEnd(keyWidth)} → ${r.priceId.padEnd(idWidth)} (${r.status})`,
    );
  }
}

main().catch((err) => {
  console.error("ERROR:", err instanceof Error ? err.message : err);
  process.exit(1);
});
