import { FC, useEffect, useRef, useState } from 'react';
import { Add, Close } from '@material-ui/icons';
import {
  Button,
  createStyles,
  FormControl,
  Grid,
  IconButton,
  InputAdornment,
  InputLabel,
  makeStyles,
  OutlinedInput,
} from '@material-ui/core';
import { clearModals, pushModal } from 'mystique/frame/pushModal';
import { getQuery } from 'mystique/hooks/getQuery';
import { Connection } from 'mystique/types/common';
import AddProductItemsModalList from './AddProductItemsModalList';
import SearchIcon from '@material-ui/icons/Search';
import _ from 'lodash';
import { useI18n } from 'mystique/hooks/useI18n';
import { useActiveRetailer } from '../../hooks/useActiveRetailer';
import { OrderItem } from '../../constants/Interfaces';

const virtualPositions = `
  query ($catalog: String!, $groupRef: [String], $after: String, $productRef: [String]) {
    virtualPositions(first: 5, catalogue: {ref: $catalog}, groupRef: $groupRef, after: $after, productRef: $productRef, status: ["ACTIVE"]) {
      edges {
        node {
          productRef
          groupRef
          quantity
          id
        }
        cursor
      }
      pageInfo {
        hasPreviousPage
        hasNextPage
      }
    }
  }
`;

interface VirtualPositionsResult {
  virtualPositions: Connection<VirtualPositionsNode>;
}

interface VirtualPositionsNode {
  productRef: string;
  quantity: number;
}

const variantProductsQuery = `
  query ($productsRef: [String!], $catalogueRef: String!) {
    variantProducts(ref: $productsRef, catalogue: {ref: $catalogueRef}, status: ["ACTIVE"]) {
      edges {
        node {
          ref
          name
          prices {
            currency
            value
          }
          attributes {
            name
            value
          }
        }
      }
    }
  }
`;

interface VariantProductsResult {
  variantProducts: Connection<VariantProductsNode>;
}

interface VariantProductsNode {
  name: string;
  ref: string;
  attributes: any;
  prices: {
    currency: string;
    price: number;
  }[];
}

export interface Product {
  ref: string;
  name: string;
  imageUrl?: string;
  quantity: number;
  attributes?: any;
  cursor: string;
  available: number;
  prices: {
    currency: string;
    value: number;
  }[];
  price?: number;
  originalPrice?: number;
}

export interface PageInfo {
  hasNextPage: boolean;
}

interface SearchParameters {
  after?: string;
  productRef?: string;
}

interface AddProductItemsModalProps {
  catalog: string;
  addItem: (value: Product) => void;
  selectedProducts: OrderItem[];
  onAddItemNumber?: number;
}

const AddProductItemsModal: FC<AddProductItemsModalProps> = ({
  catalog,
  addItem,
  onAddItemNumber,
  selectedProducts,
}) => {
  const [products, setProducts] = useState<Product[]>([]);
  const [pageInfo, setPageInfo] = useState<PageInfo>();
  const [pageHistory, setPageHistory] = useState<string[]>([]);
  const [loading, setLoading] = useState<boolean>(true);
  const searchedValue = useRef<any>('');
  const activeRetailer = useActiveRetailer();

  const { translate } = useI18n();

  const classes = useStyles();

  useEffect(() => {
    if (products.length || searchedValue.current.value || !loading) {
      refreshDataToModal();
    }
  }, [products, loading, onAddItemNumber]);

  const refreshDataToModal = () => {
    clearModals();
    openModal();
  };

  const nextPage = () => {
    const nextCursor = products[products.length - 1].cursor;
    getProducts({ after: nextCursor, productRef: searchedValue.current.value });
    setPageHistory([...pageHistory, nextCursor]);
  };

  const prevPage = () => {
    const pages = pageHistory.length;
    const prevCursor = pages > 1 ? pageHistory[pages - 2] : undefined;
    getProducts({ after: prevCursor, productRef: searchedValue.current.value });

    setPageHistory(pageHistory.filter((_, i) => i < pages - 1));
  };

  const clearSearchRequest = () => {
    searchedValue.current.value = '';
    requestSearch('');
  };

  const requestSearch = (event: string) => {
    debouncedSearch(event.trim());
  };

  const debouncedSearch = _.debounce((searchValue: string) => {
    getProducts({ productRef: searchValue });
    setPageHistory([]);
  }, 500);

  const getProducts = async (parameters?: SearchParameters) => {
    const newProducts: any[] = [];

    await getQuery<VirtualPositionsResult>(virtualPositions, {
      catalog: catalog,
      groupRef: catalog,
      productRef: parameters?.productRef ? `%${parameters?.productRef}%` : null,
      after: parameters?.after,
    }).then((resp) => {
      setLoading(true);
      setPageInfo({
        // @ts-ignore
        hasNextPage: resp.data?.virtualPositions.pageInfo.hasNextPage,
      });

      const virtualPositions = resp.data?.virtualPositions.edges?.map(
        (virtual: any) => {
          return {
            cursor: virtual.cursor,
            ref: virtual.node.productRef,
            available: virtual.node.quantity,
          };
        },
      );
      if (virtualPositions) {
        newProducts.push(...virtualPositions);
      }
    });

    if (newProducts.length) {
      await getQuery<VariantProductsResult>(variantProductsQuery, {
        productsRef: newProducts.map((product) => product.ref),
        catalogueRef: `DEFAULT:${activeRetailer}`,
      }).then((resp) => {
        resp.data?.variantProducts.edges.forEach((variantProduct) => {
          const product = newProducts.find(
            (product) => product.ref === variantProduct.node.ref,
          );
          if (product) {
            product.name = variantProduct.node.name;
            product.prices = variantProduct.node.prices;
            product.imageUrl = variantProduct.node.attributes?.byName.imageUrl;
            product.attributes = variantProduct.node.attributes;
          }
        });
      });
    }

    setProducts(newProducts);
    setLoading(false);
  };

  const openModal = () => {
    pushModal({
      title: translate('fc.se.add.product.items.add.modal.title'),
      body: (
        <>
          <Grid item className={classes.item}>
            <FormControl
              variant="outlined"
              className={classes.searchInput}
              size="small"
            >
              <InputLabel htmlFor="quick-search">
                {translate(
                  'fc.se.add.product.items.add.modal.search.product.ref',
                )}
              </InputLabel>
              <OutlinedInput
                id="quick-search"
                autoFocus={true}
                inputRef={searchedValue}
                onChange={(e) => requestSearch(e.target.value)}
                endAdornment={
                  <InputAdornment position="end">
                    <IconButton
                      disabled={
                        !(searchedValue.current && searchedValue.current.value)
                      }
                      onClick={clearSearchRequest}
                      edge="end"
                    >
                      <Close />
                    </IconButton>
                    <IconButton edge="end">
                      <SearchIcon />
                    </IconButton>
                  </InputAdornment>
                }
                label={translate(
                  'fc.se.add.product.items.add.modal.search.product.ref',
                )}
              />
            </FormControl>
          </Grid>
          <AddProductItemsModalList
            loading={loading}
            pageHistory={pageHistory}
            pageInfo={pageInfo}
            products={products}
            selectedProducts={selectedProducts}
            prevPage={prevPage}
            nextPage={nextPage}
            addItem={addItem}
          />
        </>
      ),
      actions: (
        <Button
          variant="contained"
          color="primary"
          onClick={() => {
            clearModals();
          }}
        >
          {translate('fc.se.add.product.items.add.modal.button.done')}
        </Button>
      ),
    });
  };

  return (
    <>
      <Button
        variant="text"
        size="small"
        color="primary"
        endIcon={<Add />}
        onClick={() => {
          getProducts();
          setPageHistory([]);
          openModal();
        }}
      >
        {translate('fc.se.add.product.items.add.item.button')}
      </Button>
    </>
  );
};

const useStyles = makeStyles(() =>
  createStyles({
    searchInput: {
      background: 'white',
      width: '100%',
    },
    item: {
      paddingTop: '6px',
      borderRadius: '4px',
    },
  }),
);

export default AddProductItemsModal;
