import { defaultFieldResolver, GraphQLSchema } from 'graphql'
import gql from 'graphql-tag'

import { getDirective, MapperKind, mapSchema } from '@graphql-tools/utils'

const debug = require('debug')('things-factory:notification:directive-notification')

const DIRECTIVE = 'notification'

export const notificationDirectiveTypeDefs = gql`
  directive @notification(
    receivers: String
    topic: String
    subject: String # info
    title: String
    body: String
    image: String
    url: String
    # timestamp = String(Date.now())
    mode: String # background
  ) on FIELD_DEFINITION
`
export const directiveNotification = (schema: GraphQLSchema) =>
  mapSchema(schema, {
    [MapperKind.OBJECT_FIELD]: (fieldConfig, fieldName, typeName, schema) => {
      const notificationDirective = getDirective(schema, fieldConfig, DIRECTIVE)?.[0]
      if (notificationDirective) {
        const { resolve = defaultFieldResolver, args } = fieldConfig

        if (!args) {
          throw new Error(`Unexpected Error. args should be defined in @notification directive for field ${fieldName}.`)
        }

        const {
          receivers,
          topic,
          subject = 'info',
          title,
          body,
          image,
          url,
          mode = 'background'
        } = notificationDirective
        const timestamp = Date.now()

        fieldConfig.resolve = async function (source, args, context, info) {
          const result = await resolve.call(this, source, args, context, info)

          const { domain, user, notify } = context.state

          if (!notify) {
            debug('notify not set')
          } else {
            try {
              await notify({
                receivers: [user.id],
                notificationDirective,
                timestamp: new Date()
              })
            } catch (err) {
              debug(err)
            }
          }

          return result
        }

        return fieldConfig
      }
    }
  })
