import {
   IGraphQLCartFieldsFragment,
   IGraphQLGetDataQuery,
} from '@assets/interfaces/gqlApi/graphql';
import { ICart, ICartItem, IData } from '@assets/js-shop/GraphQLInterfaces';
import config from '@assets/js-shop/config';
import { ApolloError } from '@apollo/client';
import * as Sentry from '@sentry/react';
import { IJsShopConfig, IShopDataContext } from '@assets/js-shop/Interfaces';
import { SentryUtils } from '@assets/js-shop/sentry/utils/SentryUtils';
import { LocalStorage } from '@assets/js-shop/LocalStorage';
import { sellersClearCache } from '@assets/js-shop/sellers/SellersUtil';
import { CACHE_KEY_DATA } from '@assets/js-shop/Shop';

export class ShopUtils {
   public static prepareData = (data: IGraphQLGetDataQuery): IData => {
      return {
         ...data,
         cart: ShopUtils.prepareCartData(data.cart),
         contexts: {
            ...data.contexts,
            jsShop: JSON.parse(data.contexts.jsShopConfig) as IJsShopConfig,
         },
      } as IData;
   };

   public static prepareCartData = (cart: IGraphQLCartFieldsFragment): ICart => {
      return {
         ...cart,
         items: cart.items.map((item) => {
            return { ...item, note: JSON.parse(item.note as string) } as ICartItem;
         }),
      } as ICart;
   };

   protected static activeTimers: { [name: string]: number } = {};

   static resetTimer(id: string, timeout: number, callback: () => any) {
      const timers = ShopUtils.activeTimers;
      const timer = timers[id];

      if (timer) {
         clearTimeout(timer);
      }

      // @ts-ignore
      timers[id] = setTimeout(() => {
         delete timers[id];
         callback();
      }, timeout);
   }

   static clearTimer(id: string) {
      const timers = ShopUtils.activeTimers;
      const timer = timers[id];

      if (timer) {
         clearTimeout(timer);
         delete timers[id];
      }
   }

   static isTimerActive(id: string): boolean {
      return Boolean(ShopUtils.activeTimers?.[id]).valueOf();
   }

   static validateCacheData(data: IData): boolean {
      let error: boolean | string = false;

      // @ts-ignore
      if (data?.contexts?.jsShop?.dynamicConfig) {
         return false;
      }

      if (config.moduleCart && data.cart === undefined) {
         error = 'JsShop error, tried to load invalid cache data - cart not found ';
      }

      if (error) {
         console.error(error);
         Sentry.captureMessage(error, {
            extra: { storage_data: data },
         });
         return false;
      }

      return true;
   }

   static clearElement(element: HTMLElement) {
      if (!element.dataset?.jsShopMounted) {
         element.innerHTML = '';
         element.dataset.jsShopMounted = '1';
      }
   }

   // Phone is rotated vertically
   static isScreenPhoneSizeWidth(): boolean {
      return window.matchMedia('(max-width: 768px)').matches;
   }

   // Phone is rotated horizontally
   static isScreenPhoneSizeHeight(): boolean {
      return window.matchMedia('(max-height: 520px)').matches;
   }

   // capture errors only if it's not a request abortion error
   static handleFetchError(error: ApolloError, extra: Record<string, any> = {}) {
      const skipError = [
         'Failed to fetch',
         'aborted',
         'AbortError',
         'NetworkError',
      ].some((value) => value.toLowerCase().includes(error.message.trim().toLowerCase()));

      if (skipError) {
         return;
      }

      SentryUtils.captureException(error, extra);
   }

   static clearCache() {
      LocalStorage.remove(CACHE_KEY_DATA);
      sellersClearCache();
   }

   static ignoreRefreshCookie() {
      this.refreshCookieIgnored = true
   }

   static isRefreshCookieIgnored() {
      return this.refreshCookieIgnored;
   }

   private static refreshCookieIgnored = false;
}

export function translate(key: string, errWhenMissing: boolean = true): string {
   const translations: {
      [key: string]: string;
   } = window.wpj.jsShop.translations;

   if (translations && typeof translations[key] !== 'undefined') {
      return translations[key];
   }

   if (errWhenMissing) {
      // todo: add sentry
      console.error(`Missing JSShop translation: ${key}`);

      return key;
   }
   return '';
}

export function dynamicConfig(context: IShopDataContext, configName: keyof IJsShopConfig): unknown {
   return context.contexts?.jsShop?.[configName] ?? config[configName];
}

export function getDataAttributeSelectorCamelCase(selector: string) {
   const parts = selector
      .replace(/[\[\]]/g, '')
      .split('-')
      .map((part) => {
         return part[0].toUpperCase() + part.substring(1);
      });
   parts.shift();
   return parts.join('')[0].toLowerCase() + parts.join('').substring(1);
}
