import { v4 as uuid } from 'uuid'
import { SubscriptionClient } from 'subscriptions-transport-ws'
import ApolloClient from 'apollo-client'
import VueApollo from 'vue-apollo'
import { defaultDataIdFromObject, InMemoryCache } from 'apollo-cache-inmemory'
import * as Cookie from 'js-cookie'
import { ref } from '@vue/composition-api'
import gql from 'graphql-tag'

export const clientId = uuid()

const server = process.env.NODE_ENV === 'production' ? 'wss://turnenaufzeit.de/gql' : 'ws://localhost:3000/graphql'

const client = new SubscriptionClient(server, {
  reconnect: true,
  connectionParams: () => ({
    clientId,
    token: Cookie.get('token')
  })
})

const graphQL = new ApolloClient({
  // @ts-ignore
  link: client,
  cache: new InMemoryCache({
    dataIdFromObject: object => {
      switch (object.__typename) {
        default: return defaultDataIdFromObject(object)
      }
    }
  }),
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network'
    },
    query: {
      fetchPolicy: 'no-cache'
    }
  }
})

export default new VueApollo({
  defaultClient: graphQL
})

export const useGraphQL = (context) => {
  const connected = ref(client?.client?.readyState === 1)

  client.on('connecting', () => { connected.value = false })
  client.on('connected', () => { connected.value = true })
  client.on('reconnecting', () => { connected.value = false })
  client.on('reconnected', () => { connected.value = true })
  client.on('disconnected', () => { connected.value = false })
  client.on('error', () => { connected.value = false })

  const login = async (email, passwort) => {
    try {
      const { data } = await graphQL.mutate({
        mutation: gql`mutation($email: String, $passwort: String, $token: String) { login(email: $email, passwort: $passwort, token: $token) {
          _id
          token
          givenName
          familyName
          adminOf { _id name plz ort }
        }}`,
        variables: {
          token: !email || !passwort ? Cookie.get('token') : undefined,
          email,
          passwort
        }
      })

      context.root.$store.commit('SET_PROFILE', data.login)

      Cookie.set('token', data?.login?.token, '12h', null, null, null, 'strict')
    } catch (e) {
      context.root.$store.commit('SET_PROFILE', null)

      Cookie.remove('token')

      if (email) {
        context.root.$store.commit('OPEN_SNACKBAR', 'Zugangsdaten falsch')
      }
    }
  }

  return { connected, login }
}
