// Update the authenticated member's default card in Helcim.
// Flow:
//   1. requireAuth + status gate (active | pending_payment).
//   2. Validate body (cardToken).
//   3. Verify cardToken belongs to this customer via listHelcimCustomerCards.
//   4. Capture current default card token for possible revert.
//   5. Update customer default payment method (authoritative — Helcim bills the customer default).
//   6. Update subscription payment method (best-effort belt-and-suspenders).
//      - On 4xx from step 6 (likely "unknown field" since Helcim's subscription
//        PATCH schema does not publicly document a cardToken field — see plan
//        Open Question #3): log and treat as success, since the customer
//        default already changed and is the real billing driver.
//      - On 5xx/network from step 6: attempt revert of step 5 and return 500.
//   7. logActivity on success.
import { requireAuth } from '../../utils/auth.js'
import { validateBody } from '../../utils/validateBody.js'
import { helcimUpdateCardSchema } from '../../utils/schemas.js'
import {
  listHelcimCustomerCards,
  updateHelcimCustomerDefaultPaymentMethod,
  updateHelcimSubscriptionPaymentMethod
} from '../../utils/helcim.js'
import { logActivity } from '../../utils/activityLog.js'

const ALLOWED_STATUSES = new Set(['active', 'pending_payment'])

export default defineEventHandler(async (event) => {
  const member = await requireAuth(event)

  if (!ALLOWED_STATUSES.has(member.status)) {
    throw createError({
      statusCode: 403,
      statusMessage: 'Card updates are only available for active subscriptions'
    })
  }

  if (!member.helcimCustomerId || !member.helcimSubscriptionId) {
    throw createError({
      statusCode: 400,
      statusMessage: 'No active subscription on file'
    })
  }

  const body = await validateBody(event, helcimUpdateCardSchema)
  const { cardToken } = body

  // Step 3: verify the submitted token is attached to this member's customer
  const cardsResponse = await listHelcimCustomerCards(member.helcimCustomerId)
  const cards = Array.isArray(cardsResponse)
    ? cardsResponse
    : (cardsResponse?.cards || cardsResponse?.data || [])

  const matchingCard = cards.find((c) => c?.cardToken === cardToken)
  if (!matchingCard) {
    throw createError({
      statusCode: 403,
      statusMessage: 'Card token does not belong to this customer'
    })
  }

  // Step 4: capture prior default card token for possible revert
  const priorDefault = cards.find((c) => c?.default === true || c?.isDefault === true)
  const priorCardToken = priorDefault?.cardToken || null

  // Step 5: authoritative change — update customer default
  try {
    await updateHelcimCustomerDefaultPaymentMethod(member.helcimCustomerId, cardToken)
  } catch (error) {
    console.error('[update-card] Customer default update failed', {
      memberId: String(member._id),
      error: error?.statusMessage || error?.message || error
    })
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to update payment method'
    })
  }

  // Step 6: best-effort subscription payment-method update.
  // Plan Open Question #3: Helcim's subscription PATCH does not publicly
  // document a cardToken field. We tolerate 4xx (unknown field / schema
  // rejection) because step 5 — the customer default — is authoritative.
  // On 5xx/network errors we treat state as untrusted and attempt revert.
  try {
    await updateHelcimSubscriptionPaymentMethod(member.helcimSubscriptionId, cardToken)
  } catch (error) {
    const status = Number(error?.statusCode) || 0
    const isClientError = status >= 400 && status < 500

    if (isClientError) {
      console.warn('[update-card] Subscription PATCH rejected (4xx); treating as best-effort', {
        memberId: String(member._id),
        status,
        message: error?.statusMessage || error?.message
      })
      // fall through to success — customer default is the billing driver
    } else {
      // 5xx / network / unknown — revert customer default if we can
      console.error('[update-card] Subscription update failed with server error; attempting revert', {
        memberId: String(member._id),
        status,
        error: error?.statusMessage || error?.message || error
      })

      if (priorCardToken) {
        try {
          await updateHelcimCustomerDefaultPaymentMethod(member.helcimCustomerId, priorCardToken)
        } catch (revertError) {
          console.error('[update-card] Revert also failed — INCONSISTENT STATE', {
            memberId: String(member._id),
            helcimCustomerId: member.helcimCustomerId,
            revertError: revertError?.statusMessage || revertError?.message || revertError
          })
        }
      } else {
        console.error('[update-card] No prior default card to revert to', {
          memberId: String(member._id)
        })
      }

      throw createError({
        statusCode: 500,
        statusMessage: 'Failed to update payment method'
      })
    }
  }

  // Step 7: success
  await logActivity(member._id, 'billing_card_updated', {}, { visibility: 'member' })

  return { success: true }
})
