import { E_VAULT_KEY_EXISTS, GqlAuthenticationError, GqlInputError } from '@/lib/error'

export default {
  Query: {
    getVaultEntry: async (parent, { key }, { me, models }, info) => {
      if (!me) throw new GqlAuthenticationError()
      if (!key) throw new GqlInputError('must have key')

      const k = await models.vault.findUnique({
        where: {
          key,
          userId: me.id
        }
      })
      return k
    },
    getVaultEntries: async (parent, { keysFilter }, { me, models }, info) => {
      if (!me) throw new GqlAuthenticationError()

      const entries = await models.vaultEntry.findMany({
        where: {
          userId: me.id,
          key: keysFilter?.length
            ? {
                in: keysFilter
              }
            : undefined
        }
      })
      return entries
    }
  },
  Mutation: {
    // atomic vault migration
    updateVaultKey: async (parent, { entries, hash }, { me, models }) => {
      if (!me) throw new GqlAuthenticationError()
      if (!hash) throw new GqlInputError('hash required')
      const txs = []

      const { vaultKeyHash: oldKeyHash } = await models.user.findUnique({ where: { id: me.id } })
      if (oldKeyHash) {
        if (oldKeyHash !== hash) {
          throw new GqlInputError('vault key already set', E_VAULT_KEY_EXISTS)
        } else {
          return true
        }
      } else {
        txs.push(models.user.update({
          where: { id: me.id },
          data: { vaultKeyHash: hash }
        }))
      }

      for (const entry of entries) {
        console.log(entry)
        txs.push(models.vaultEntry.update({
          where: { userId_key: { userId: me.id, key: entry.key } },
          data: { value: entry.value, iv: entry.iv }
        }))
      }
      await models.$transaction(txs)
      return true
    },
    clearVault: async (parent, args, { me, models }) => {
      if (!me) throw new GqlAuthenticationError()
      const txs = []
      txs.push(models.user.update({
        where: { id: me.id },
        data: { vaultKeyHash: '' }
      }))
      txs.push(models.vaultEntry.deleteMany({ where: { userId: me.id } }))
      await models.$transaction(txs)
      return true
    }
  }
}