/**
 * Reconcile Helcim transactions → Payment docs in Mongo.
 *
 * For every Member with a helcimCustomerId, fetch their recent Helcim
 * transactions and upsert a Payment row for each one. Idempotent: existing
 * Payment docs (keyed by helcimTransactionId) are never overwritten. Skips
 * transactions with status 'other' (verify/auth-only etc.).
 *
 * Usage:
 *   node scripts/reconcile-helcim-payments.mjs            # dry-run (default)
 *   node scripts/reconcile-helcim-payments.mjs --apply    # writes new Payment rows
 *
 * Uses:
 *   - Launch-day backfill for pre-existing members.
 *   - Ongoing reconciliation (nightly cron) to catch Helcim-initiated recurring
 *     charges that bypass the synchronous write paths in subscription.post.js
 *     and update-contribution.post.js.
 *
 * Required env: MONGODB_URI, HELCIM_API_TOKEN
 */

import dotenv from 'dotenv'
import { fileURLToPath } from 'url'
import { dirname, resolve } from 'path'
import mongoose from 'mongoose'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
dotenv.config({ path: resolve(__dirname, '../.env') })

// Nitro auto-imports used inside server/utils/helcim.js — shim them so the
// util module loads outside the Nitro runtime.
globalThis.useRuntimeConfig = () => ({ helcimApiToken: process.env.HELCIM_API_TOKEN })
globalThis.createError = (opts = {}) => {
  const err = new Error(opts.statusMessage || 'Error')
  Object.assign(err, opts)
  return err
}

const { default: Member } = await import('../server/models/member.js')
const { default: Payment } = await import('../server/models/payment.js')
const { listHelcimCustomerTransactions } = await import('../server/utils/helcim.js')
const { upsertPaymentFromHelcim } = await import('../server/utils/payments.js')

async function run() {
  const apply = process.argv.includes('--apply')

  if (!process.env.MONGODB_URI) {
    console.error('MONGODB_URI not set in environment')
    process.exit(1)
  }
  if (!process.env.HELCIM_API_TOKEN) {
    console.error('HELCIM_API_TOKEN not set in environment')
    process.exit(1)
  }

  await mongoose.connect(process.env.MONGODB_URI)

  const members = await Member.find(
    { helcimCustomerId: { $exists: true, $ne: null } },
    { _id: 1, email: 1, name: 1, helcimCustomerId: 1, helcimSubscriptionId: 1, billingCadence: 1 }
  ).lean()

  console.log(`Scanning ${members.length} members with helcimCustomerId`)

  let txExamined = 0
  let created = 0
  let existed = 0
  let skipped = 0
  let memberErrors = 0

  for (const member of members) {
    let txs
    try {
      txs = await listHelcimCustomerTransactions(member.helcimCustomerId)
    } catch (err) {
      memberErrors++
      console.error(`  ERR member=${member._id} (${member.email}): ${err?.message || err}`)
      continue
    }

    for (const tx of txs) {
      txExamined++
      if (tx.status === 'other') {
        skipped++
        continue
      }

      if (!apply) {
        const existing = await Payment.findOne({ helcimTransactionId: tx.id })
        if (existing) existed++
        else created++
        continue
      }

      const result = await upsertPaymentFromHelcim(member, tx)
      if (result.created) created++
      else if (result.payment) existed++
      else skipped++
    }
  }

  const verb = apply ? 'Created' : 'Would create'
  console.log(`\nMembers scanned: ${members.length}`)
  console.log(`Transactions examined: ${txExamined}`)
  console.log(`${verb}: ${created}`)
  console.log(`Already existed: ${existed}`)
  console.log(`Skipped (status=other or unmapped): ${skipped}`)
  if (memberErrors > 0) console.log(`Helcim API errors for members: ${memberErrors}`)
  if (!apply) console.log('\nDry-run complete. Re-run with --apply to write Payment rows.')

  await mongoose.disconnect()
}

run().catch(async (err) => {
  console.error(err)
  try {
    await mongoose.disconnect()
  } catch {}
  process.exit(1)
})
