/* eslint-disable no-console */
/**
 * Benchmark Seed Script
 *
 * Creates test data required for Payment Kit benchmarks:
 *   1. Meter (credit type, with currency)
 *   2. Product + metered Price
 *   3. Customer (via checkout or existing)
 *   4. Credit Grants (large balance for sustained testing)
 *
 * Usage:
 *   pnpm run benchmark-seed --app-id <APP_ID>
 *
 * Or with blocklet exec:
 *   blocklet exec /scripts/benchmark-seed.js --app-id <APP_ID>
 *
 * After running, copy the output env vars to benchmarks/.env
 */
const { spawn } = require('child_process');
const payment = require('../../../packages/client/lib').default;

function getAppId() {
  const args = process.argv.slice(2);
  let appId = '';
  for (let i = 0; i < args.length; i++) {
    if (args[i] === '--app-id' && i + 1 < args.length) {
      appId = args[i + 1];
      break;
    }
  }
  if (!appId) {
    appId =
      process.env.BLOCKLET_DEV_APP_DID?.split(':').pop() ||
      process.env.BLOCKLET_APP_ID ||
      'zNKuN3XwXN7xq2NsJQjjfwujyqCxx26DhwgV';
  }
  return appId;
}

// Configuration
const CREDIT_GRANT_AMOUNT = 1000000; // 1M credits - enough for thousands of benchmark events
const CUSTOMER_COUNT = 3; // Multi-customer for parallelism testing
const METER_EVENT_NAME = 'benchmark_credits';
const METER_UNIT = 'Token';

async function findOrCreateMeter() {
  console.log('\n── Step 1: Find or create meter ──');

  // Try to find existing meter
  try {
    const meters = await payment.meters.list({ limit: 50 });
    const items = meters?.list || meters?.data || [];
    const existing = items.find((m) => m.event_name === METER_EVENT_NAME);
    if (existing) {
      console.log(`  Found existing meter: ${existing.id} (event_name=${existing.event_name}, currency=${existing.currency_id})`);
      return existing;
    }
  } catch (err) {
    console.log(`  Could not list meters: ${err.message}`);
  }

  // Create new meter
  const meter = await payment.meters.create({
    name: 'Benchmark Credits',
    event_name: METER_EVENT_NAME,
    aggregation_method: 'sum',
    unit: METER_UNIT,
    description: 'Benchmark test meter for credit consumption',
    created_via: 'api',
  });
  console.log(`  Created meter: ${meter.id} (event_name=${meter.event_name}, currency=${meter.currency_id})`);
  return meter;
}

async function findOrCreateProduct(meter) {
  console.log('\n── Step 2: Find or create metered product + price ──');

  // Try to find existing
  try {
    const products = await payment.products.list({ limit: 50 });
    const items = products?.list || products?.data || [];
    const existing = items.find((p) => p.name === 'Benchmark Metered Service');
    if (existing) {
      console.log(`  Found existing product: ${existing.id}`);
      // Find price for this product
      const prices = await payment.prices.list({ product_id: existing.id, limit: 10 });
      const priceList = prices?.list || prices?.data || [];
      if (priceList.length > 0) {
        console.log(`  Found existing price: ${priceList[0].id}`);
        return { product: existing, price: priceList[0] };
      }
    }
  } catch (err) {
    console.log(`  Could not list products: ${err.message}`);
  }

  const product = await payment.products.create({
    name: 'Benchmark Metered Service',
    description: 'Product for benchmark testing',
    type: 'credit',
    prices: [
      {
        type: 'recurring',
        unit_amount: '0.001',
        currency_id: meter.currency_id,
        nickname: 'Benchmark metered price',
        recurring: {
          interval: 'month',
          interval_count: 1,
          usage_type: 'metered',
          meter_id: meter.id,
          aggregate_usage: 'sum',
        },
        metadata: {
          credit_config: {
            priority: 50,
            valid_duration_value: 0,
            valid_duration_unit: 'days',
            currency_id: meter.currency_id,
            credit_amount: '1',
          },
          meter_id: meter.id,
        },
      },
    ],
  });

  const prices = product.prices || [];
  const price = prices[0];
  console.log(`  Created product: ${product.id}`);
  console.log(`  Created price: ${price?.id}`);
  return { product, price };
}

async function getCustomers() {
  console.log('\n── Step 3: Find customers ──');

  const result = await payment.customers.list({ limit: CUSTOMER_COUNT });
  const items = result?.list || result?.data || [];

  if (items.length === 0) {
    console.log('  No customers found. Please create customers first (e.g. via checkout).');
    console.log('  Tip: Log in to the blocklet UI as different users to auto-create customers.');
    process.exit(1);
  }

  console.log(`  Found ${items.length} customer(s):`);
  for (const c of items) {
    console.log(`    ${c.id}: ${c.name || c.email || c.did || '(unnamed)'}`);
  }

  return items.slice(0, CUSTOMER_COUNT);
}

async function ensureCreditGrants(customers, meter) {
  console.log('\n── Step 4: Ensure credit grants ──');

  for (const customer of customers) {
    // Check existing balance
    let existingBalance = '0';
    try {
      const summary = await payment.creditGrants.summary({ customer_id: customer.id });
      const balances = summary?.balances || summary?.data || [];
      const match = balances.find((b) => b.currency_id === meter.currency_id);
      existingBalance = match?.available || match?.remaining_amount || '0';
    } catch {
      // ignore
    }

    const needsGrant = Number(existingBalance) < CREDIT_GRANT_AMOUNT / 2;

    if (needsGrant) {
      const grant = await payment.creditGrants.create({
        customer_id: customer.id,
        amount: CREDIT_GRANT_AMOUNT,
        currency_id: meter.currency_id,
        category: 'promotional',
        name: 'Benchmark credit grant',
        applicability_config: {
          scope: {
            price_type: 'metered',
          },
        },
      });
      console.log(`  Created grant for ${customer.id}: ${grant.id} (amount=${CREDIT_GRANT_AMOUNT})`);
    } else {
      console.log(`  ${customer.id}: balance=${existingBalance}, sufficient`);
    }
  }
}

async function runSeed() {
  payment.environments.setTestMode(true);

  console.log('=== Payment Kit Benchmark Seed ===');
  console.log(`  Grant amount per customer: ${CREDIT_GRANT_AMOUNT}`);
  console.log(`  Meter event name: ${METER_EVENT_NAME}`);

  const meter = await findOrCreateMeter();
  const { price } = await findOrCreateProduct(meter);
  const customers = await getCustomers();
  await ensureCreditGrants(customers, meter);

  // Output env vars for benchmarks/.env
  const customerIds = customers.map((c) => c.id);
  console.log('\n\n=== Copy to benchmarks/.env ===\n');
  console.log(`METER_EVENT_NAME=${METER_EVENT_NAME}`);
  console.log(`CUSTOMER_ID=${customerIds[0]}`);
  if (customerIds.length > 1) {
    console.log(`CUSTOMER_IDS=${customerIds.join(',')}`);
  }
  if (price) {
    console.log(`# PRICE_ID=${price.id}`);
  }
  console.log(`# METER_ID=${meter.id}`);
  console.log(`# CURRENCY_ID=${meter.currency_id}`);
  console.log(`# CREDIT_GRANT_AMOUNT=${CREDIT_GRANT_AMOUNT}`);

  console.log('\n=== Seed complete ===');
}

async function main() {
  if (process.env.BLOCKLET_APP_ID) {
    await runSeed();
    process.exit(0);
  }

  const appId = getAppId();
  const args = process.argv.slice(2).filter((arg) => arg !== '--app-id' && arg !== appId);

  console.log(`Running with blocklet exec, app-id: ${appId}`);

  const child = spawn('blocklet', ['exec', '/scripts/benchmark-seed.js', '--app-id', appId, ...args], {
    stdio: 'inherit',
  });

  child.on('exit', (code) => {
    process.exit(code || 0);
  });
}

if (require.main === module) {
  main().catch((error) => {
    console.error('Seed failed:', error);
    process.exit(1);
  });
}
