import { PAID_ACTION_PAYMENT_METHODS, TERRITORY_PERIOD_COST } from '@/lib/constants'
import { satsToMsats } from '@/lib/format'
import { nextBilling } from '@/lib/territory'
import { initialTrust } from './lib/territory'

export const anonable = false

export const paymentMethods = [
  PAID_ACTION_PAYMENT_METHODS.FEE_CREDIT,
  PAID_ACTION_PAYMENT_METHODS.REWARD_SATS,
  PAID_ACTION_PAYMENT_METHODS.PESSIMISTIC
]

export async function getCost ({ billingType }) {
  return satsToMsats(TERRITORY_PERIOD_COST(billingType))
}

export async function perform ({ name, invoiceId, ...data }, { me, cost, tx }) {
  const sub = await tx.sub.findUnique({
    where: {
      name
    }
  })

  data.billingCost = TERRITORY_PERIOD_COST(data.billingType)

  // we never want to bill them again if they are changing to ONCE
  if (data.billingType === 'ONCE') {
    data.billPaidUntil = null
    data.billingAutoRenew = false
  }

  data.billedLastAt = new Date()
  data.billPaidUntil = nextBilling(data.billedLastAt, data.billingType)
  data.status = 'ACTIVE'
  data.userId = me.id

  if (sub.userId !== me.id) {
    try {
      // XXX this will throw if this transfer has already happened
      // TODO: upsert this
      await tx.territoryTransfer.create({ data: { subName: name, oldUserId: sub.userId, newUserId: me.id } })
      // this will throw if the prior user has already unsubscribed
      await tx.subSubscription.delete({ where: { userId_subName: { userId: sub.userId, subName: name } } })
    } catch (e) {
      console.error(e)
    }
  }

  await tx.subAct.create({
    data: {
      userId: me.id,
      subName: name,
      msats: cost,
      type: 'BILLING'
    }
  })

  await tx.subSubscription.upsert({
    where: {
      userId_subName: {
        userId: me.id,
        subName: name
      }
    },
    update: {
      userId: me.id,
      subName: name
    },
    create: {
      userId: me.id,
      subName: name
    }
  })

  const updatedSub = await tx.sub.update({
    data,
    // optimistic concurrency control
    // make sure none of the relevant fields have changed since we fetched the sub
    where: {
      ...sub,
      postTypes: {
        equals: sub.postTypes
      }
    }
  })

  const trust = initialTrust({ name: updatedSub.name, userId: updatedSub.userId })
  for (const t of trust) {
    await tx.userSubTrust.upsert({
      where: {
        userId_subName: { userId: t.userId, subName: t.subName }
      },
      update: t,
      create: t
    })
  }

  return updatedSub
}

export async function describe ({ name }, context) {
  return `SN: unarchive territory ${name}`
}
