import { ApolloProvider } from "@apollo/react-common";
import { ApolloLink } from "apollo-boost";
import { InMemoryCache } from "apollo-cache-inmemory";
import ApolloClient from "apollo-client";
import { split } from "apollo-link";
import { setContext } from "apollo-link-context";
import { HttpLink } from "apollo-link-http";
import apolloLogger from "apollo-link-logger";
import { RetryLink } from "apollo-link-retry";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
import React, { Component } from "react";
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
import { auth } from "../firebase/firebase.utils";
import errorLink from "../graphql/apollo-error-handling";
import App from "./App";

import LogRocket from "logrocket";
LogRocket.init("gvfvfw/bodyshopapp");

export default class AppContainer extends Component {
  constructor() {
    super();
    const httpLink = new HttpLink({
      uri: process.env.REACT_APP_GRAPHQL_ENDPOINT,
    });

    const wsLink = new WebSocketLink({
      uri: process.env.REACT_APP_GRAPHQL_ENDPOINT_WS,
      options: {
        lazy: true,
        reconnect: true,
        connectionParams: async () => {
          //const token = localStorage.getItem("token");
          const token = await auth.currentUser.getIdToken(true);
          if (token) {
            return {
              headers: {
                authorization: token ? `Bearer ${token}` : "",
              },
            };
          }
        },
      },
    });
    const subscriptionMiddleware = {
      applyMiddleware: async (options, next) => {
        options.authToken = await auth.currentUser.getIdToken(true);
        next();
      },
    };
    wsLink.subscriptionClient.use([subscriptionMiddleware]);

    const link = split(
      // split based on operation type
      ({ query }) => {
        const definition = getMainDefinition(query);
        // console.log(
        //   "##Intercepted GQL Transaction : " +
        //     definition.operation +
        //     "|" +
        //     definition.name.value +
        //     "##",
        //   query
        // );
        return (
          definition.kind === "OperationDefinition" &&
          definition.operation === "subscription"
        );
      },
      wsLink,
      httpLink
    );

    const authLink = setContext((_, { headers }) => {
      return auth.currentUser.getIdToken().then((token) => {
        if (token) {
          return {
            headers: {
              ...headers,
              authorization: token ? `Bearer ${token}` : "",
            },
          };
        } else {
          return { headers };
        }
      });
    });

    const retryLink = new RetryLink({
      delay: {
        initial: 300,
        max: 5,
        jitter: true,
      },
      attempts: {
        max: 5,
        retryIf: (error, _operation) => !!error,
      },
    });

    const middlewares = [];
    if (process.env.NODE_ENV === "development") {
      middlewares.push(apolloLogger);
    }

    middlewares.push(retryLink.concat(errorLink.concat(authLink.concat(link))));

    const cache = new InMemoryCache();
    const client = new ApolloClient({
      link: ApolloLink.from(middlewares),
      cache,
      connectToDevTools: true,
    });

    this.state = { client };
  }

  render() {
    const { client } = this.state;

    return (
      <ApolloProvider client={client}>
        <GlobalLoadingBar />
        <App />
      </ApolloProvider>
    );
  }
}
