#!/usr/bin/env bun
// Fast MRR calculation using balance_transactions (much faster than paginating invoices)
// Usage: STRIPE_SECRET_KEY=sk_... bun stripe-mrr.ts

const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
if (!STRIPE_SECRET_KEY) {
  console.error("STRIPE_SECRET_KEY not set");
  process.exit(1);
}

const stripeApi = async (endpoint: string, params?: Record<string, string>) => {
  const url = new URL(`https://api.stripe.com/v1${endpoint}`);
  if (params) Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${STRIPE_SECRET_KEY}` },
  });
  return res.json();
};

// Fetch with pagination but with better limits
const fetchPages = async (endpoint: string, params: Record<string, string>, maxItems = 500) => {
  const items: any[] = [];
  let startingAfter: string | undefined;
  
  while (items.length < maxItems) {
    const reqParams = { ...params, limit: "100" };
    if (startingAfter) reqParams.starting_after = startingAfter;
    
    const data = await stripeApi(endpoint, reqParams);
    if (!data.data?.length) break;
    
    items.push(...data.data);
    if (!data.has_more) break;
    startingAfter = data.data[data.data.length - 1].id;
  }
  return items;
};

const getChargeEmail = (charge: any): string | null => {
  return charge.billing_details?.email || charge.receipt_email || null;
};

const main = async () => {
  const now = new Date();
  const currentMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
  
  // Get start of last month and current month
  const lastMonthStart = new Date(now.getFullYear(), now.getMonth() - 1, 1);
  const currentMonthStart = new Date(now.getFullYear(), now.getMonth(), 1);
  const lastMonthKey = `${lastMonthStart.getFullYear()}-${String(lastMonthStart.getMonth() + 1).padStart(2, "0")}`;
  
  // Fetch from 6 months ago for historical revenue data
  const lookbackStart = new Date(now.getFullYear(), now.getMonth() - 6, 1);
  
  console.error("Fetching charges...");
  
  // Fetch charges (has email info, unlike balance_transactions)
  const allCharges = await fetchPages("/charges", {
    "created[gte]": Math.floor(lookbackStart.getTime() / 1000).toString(),
  }, 5000);
  
  // Filter to successful paid charges only (no domain exclusions)
  const charges = allCharges.filter(c => c.paid && c.amount > 0);
  
  console.error(`Found ${allCharges.length} total charges, ${charges.length} paid`);
  
  // Aggregate by month (using charge amount - fee for net)
  const monthlyRevenue: Record<string, number> = {};
  for (const charge of charges) {
    const date = new Date(charge.created * 1000);
    const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`;
    // Use amount captured minus Stripe fees (balance_transaction.fee if available)
    const amount = (charge.amount - (charge.balance_transaction?.fee || 0)) / 100;
    monthlyRevenue[monthKey] = (monthlyRevenue[monthKey] || 0) + amount;
  }
  
  // Get active subscription count (v1 subs - may be 0 for v2 billing)
  const activeSubs = await stripeApi("/subscriptions", { status: "active", limit: "1" });
  
  // Count unique paying customers (last 2 months only for the headline number)
  const recentCharges = charges.filter(c => {
    const date = new Date(c.created * 1000);
    return date >= lastMonthStart;
  });
  const uniqueCustomers = new Set(recentCharges.map(c => c.customer));
  
  // Top customers by spend (last 2 months)
  const customerSpend: Record<string, { email: string; total: number }> = {};
  for (const charge of recentCharges) {
    const cust = charge.customer;
    const email = getChargeEmail(charge) || "unknown";
    if (!customerSpend[cust]) {
      customerSpend[cust] = { email, total: 0 };
    }
    customerSpend[cust].total += charge.amount / 100;
  }
  
  const topCustomers = Object.values(customerSpend)
    .sort((a, b) => b.total - a.total)
    .slice(0, 10)
    .map(c => ({ email: c.email, revenue: Math.round(c.total * 100) / 100 }));

  const result = {
    generated_at: new Date().toISOString(),
    mrr_month: lastMonthKey,
    mrr_net: Math.round((monthlyRevenue[lastMonthKey] || 0) * 100) / 100,
    current_month: currentMonth,
    current_month_net: Math.round((monthlyRevenue[currentMonth] || 0) * 100) / 100,
    paid_customers: uniqueCustomers.size,
    v1_active_subscriptions: activeSubs.data?.length || 0,
    top_customers: topCustomers,
    monthly_net_revenue: Object.entries(monthlyRevenue)
      .map(([month, net]) => ({ month, net: Math.round(net * 100) / 100 }))
      .sort((a, b) => b.month.localeCompare(a.month)),
  };

  console.log(JSON.stringify(result, null, 2));
};

main().catch(console.error);
