import { FC, useEffect, useRef, useState } from 'react';
import { makeStyles, TextField, Theme, Typography } from '@material-ui/core';
import AddProductItemsModal, { Product } from './AddProductItemsModal';
import { useI18n } from 'mystique/hooks/useI18n';
import { pushToast } from 'mystique/frame/pushToast';
import clsx from 'clsx';
import _ from 'lodash';
import { TemplateRegistry } from 'mystique/registry/TemplateRegistry';
import { FieldRegistry } from 'mystique/registry/FieldRegistry';
import RemoveButton from '../buttons/RemoveButton';
import AddProductItemsTable from './AddProductItemsTable';
import { Alert, AlertTitle } from '@material-ui/lab';
import { getSettings } from 'mystique/hooks/getSettings';
import { getQuery } from 'mystique/hooks/getQuery';
import { Connection } from 'mystique/types/common';
import { useTemplateRender } from '../../hooks/useTemplateRender';
import { useActiveRetailer } from '../../hooks/useActiveRetailer';
import { useDefaultTariffValue } from '../../hooks/useDefaultTariffValue';
import { aggregateCatalogueForItemsSettingName } from '../../constants/SettingNames';
import { OrderItem, VirtualCatalogue } from '../../constants/Interfaces';

interface VirtualPositionsResult {
  virtualPositions: Connection<VirtualPositionsNode>;
}

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

interface AddProductItemsProps {
  onChange: (value: unknown, property: string) => void;
  products: OrderItem[];
  defaultProduct?: Product;
  price?: number;
  totalTaxPrice?: number;
  tableView?: boolean;
}

const virtualPositionsQuery = `
  query ($catRef: String!, $first: Int!) {
    virtualPositions(catalogue: {ref: $catRef} first: $first) {
      edges {
        node {
          ref
          productRef
          quantity
          groupRef
        }
      }
    }
  }
`;

const AddProductItems: FC<AddProductItemsProps> = ({
  products,
  defaultProduct,
  onChange,
  price,
  totalTaxPrice,
  tableView,
}) => {
  const [catalogue, setCatalogue] = useState<VirtualCatalogue | null>();
  const classes = useStyles();
  const templateRender = useTemplateRender();
  const QuantitySelector = FieldRegistry.get<number>('number');
  const onAddItemNumber = useRef<number>(0);

  const { translate } = useI18n();

  const tariffValue = useDefaultTariffValue();

  const activeRetailer = useActiveRetailer();

  useEffect(() => {
    getCatalogue().then(setCatalogue);
  }, []);

  const getCatalogue = async () => {
    let newCatalogue: VirtualCatalogue | null = null;

    await getSettings({ setting: aggregateCatalogueForItemsSettingName }).then(
      (value) => {
        if (value.setting.status == 'ok') {
          newCatalogue = {
            ref: `${value.setting.result.value}:${activeRetailer}`,
          };
        }
      },
    );

    if (newCatalogue != null) {
      await getQuery<VirtualPositionsResult>(virtualPositionsQuery, {
        // @ts-ignore
        catRef: newCatalogue.ref,
        first: 1,
      }).then((resp) => {
        if (newCatalogue != null)
          newCatalogue.type =
            resp.data?.virtualPositions.edges[0].node.groupRef ===
            newCatalogue.ref
              ? 'aggregate'
              : 'base';
      });
    }

    return newCatalogue;
  };

  useEffect(() => {
    if (catalogue && defaultProduct && tariffValue) {
      if (!products || products.length == 0) {
        addItem(defaultProduct);
      }
    }
  }, [catalogue, tariffValue]);

  const addItem = (product: Product) => {
    const newItem: OrderItem = {
      ref: product.ref,
      name: product.name,
      imageUrl: product.imageUrl,
      quantity: 1,
      available: product.available,
      prices: product.prices,
      price: product.prices[0].value,
      originalPrice: product.prices[0].value,
      taxPrice: product.prices[0].value * tariffValue,
      attributes: product.attributes,
    };

    pushToast(
      'success',
      `${translate('fc.se.add.product.items.item.added')} - ${
        newItem.ref
      } ${translate('fc.se.add.product.items.item.added.to.order')}`,
      3000,
    );
    AddNewProductAndPrice();
    onAddItemNumber.current += 1;

    function AddNewProductAndPrice() {
      const newProducts: OrderItem[] = _.cloneDeep(products);
      newProducts.push(newItem);
      onChange(newProducts, 'products');
      onChange((price || 0) + newItem.prices[0].value, 'totalPrice');
    }
  };

  const deleteProduct = (ref: string) => {
    const newProducts = _.cloneDeep(products);
    let newPrice = 0;
    newProducts.splice(
      products.findIndex((item) => ref === item.ref),
      1,
    );
    newProducts.forEach((product: any) => {
      newPrice += product.price * product.quantity;
    });
    onChange(newProducts, 'products');
    onChange(newPrice, 'totalPrice');
  };

  const changeProduct = (ref: string, name: string, value: any) => {
    let newPrice = 0;

    const newProducts: Product[] = products.map((product: any) => {
      if (ref === product.ref) {
        product[name] = value;
      }
      newPrice += product.price * product.quantity;
      return product;
    });
    onChange(newProducts, 'products');
    onChange(newPrice, 'totalPrice');
  };

  const renderCurrency = (value: number, currency: string) =>
    TemplateRegistry.render(`{{currency ${value} '${currency}'}}`);

  return (
    <>
      {catalogue === null ? (
        <Alert severity="error">
          <AlertTitle>
            {translate('fc.se.add.product.items.error.label')}
          </AlertTitle>
          {translate('fc.se.add.product.items.error.empty.setting', {
            settingName: aggregateCatalogueForItemsSettingName,
          })}
        </Alert>
      ) : catalogue != undefined && catalogue?.type !== 'aggregate' ? (
        <Alert severity="error">
          <AlertTitle>
            {translate('fc.se.add.product.items.error.label')}
          </AlertTitle>
          {translate('fc.se.add.product.items.error.not.aggregate.setting', {
            settingName: aggregateCatalogueForItemsSettingName,
          })}
        </Alert>
      ) : (
        catalogue?.type === 'aggregate' && (
          <>
            <AddProductItemsModal
              catalog={catalogue.ref}
              selectedProducts={products}
              addItem={addItem}
              onAddItemNumber={onAddItemNumber.current}
            />

            <div className={classes.fullWidth}>
              {!tableView
                ? products.map((product: OrderItem) => (
                  <div className={classes.product} key={product.ref}>
                    <RemoveButton
                      className={classes.deleteButton}
                      id={product.ref}
                      onClick={deleteProduct}
                    />
                    <div className={classes.productContainer}>
                      <div className={classes.productContainerText}>
                        <div className={classes.productWrapper}>
                          <div className={classes.productProperty}>
                            <Typography variant="body2">
                              {translate('fc.se.add.product.items.product')}
                            </Typography>
                          </div>
                          <div className={classes.productValue}>
                            <Typography variant="body1">
                              {product.name}
                            </Typography>
                          </div>
                        </div>
                        <div className={classes.productWrapper}>
                          <div className={classes.productProperty}>
                            <Typography variant="body2">
                              {translate('fc.se.add.product.items.ref.no')}
                            </Typography>
                          </div>
                          <div className={classes.productValue}>
                            <Typography variant="body1">
                              {product.ref}
                            </Typography>
                          </div>
                        </div>
                      </div>
                      <img
                        className={classes.productImg}
                        src={product.imageUrl}
                        alt=""
                      />
                    </div>
                    <div className={classes.productWrapper}>
                      <div className={classes.productProperty}>
                        <Typography variant="body2">
                          {translate('fc.se.add.product.items.quantity')} (
                          {product.available})
                        </Typography>
                      </div>
                    </div>
                    <QuantitySelector
                      name={`quantity[${product.ref}]`}
                      label={''}
                      value={product.quantity}
                      validation={{
                        min: 1,
                        max: product.available,
                      }}
                      onChange={(e) =>
                        changeProduct(product.ref, 'quantity', e)
                      }
                      onBlur={() => ''}
                    />
                    <>
                      <TextField
                        name={`price[${product.ref}]`}
                        label={`${translate(
                          'fc.se.add.product.items.unit.price',
                        )}  (${templateRender(
                          `{{currencySymbol '${product.prices[0].currency}'}}`,
                        )})`}
                        value={product.price}
                        className={classes.priceField}
                        onChange={(e) =>
                          changeProduct(product.ref, 'price', e.target.value)
                        }
                        onBlur={() => ''}
                        autoComplete="off"
                        fullWidth
                        size="small"
                        variant="standard"
                        inputProps={{ min: 0 }}
                        InputLabelProps={{ shrink: true }}
                        onKeyPress={(event) => {
                          if (event?.key === '-' || event?.key === '+') {
                            event.preventDefault();
                          }
                        }}
                      />
                      <div
                        className={clsx(classes.priceWas, {
                          [classes.hidden]:
                              product.originalPrice == product.price,
                        })}
                      >
                        <Typography variant="body2">
                          {translate('fc.se.add.product.items.was')}{' '}
                          {product.originalPrice}
                        </Typography>
                      </div>
                    </>
                  </div>
                ))
                : !!products.length && (
                  <AddProductItemsTable
                    onDelete={deleteProduct}
                    onChangeQuantity={changeProduct}
                    products={products}
                  />
                )}
            </div>
            {!!price && !!totalTaxPrice && (
              <div className={classes.fullWidth}>
                <Typography
                  className={classes.totalPrice}
                  align={'right'}
                  component="h4"
                  variant="h4"
                >
                  {translate('fc.se.add.product.items.taxes')}:{' '}
                  {renderCurrency(
                    totalTaxPrice,
                    products[0]?.prices[0].currency,
                  )}
                </Typography>
                <Typography
                  className={classes.totalPrice}
                  align={'right'}
                  component="h4"
                  variant="h4"
                >
                  {translate('fc.se.add.product.items.subtotal')}:{' '}
                  {renderCurrency(price, products[0]?.prices[0].currency)}
                </Typography>
                <div className={classes.bottom}>
                  <Typography
                    className={classes.totalPrice}
                    align={'right'}
                    component="h3"
                    variant="h3"
                  >
                    {translate('fc.se.add.product.items.total.price')}:{' '}
                    {renderCurrency(
                      price + totalTaxPrice,
                      products[0]?.prices[0].currency,
                    )}
                  </Typography>
                </div>
              </div>
            )}
          </>
        )
      )}
    </>
  );
};

const useStyles = makeStyles((theme: Theme) => ({
  fullWidth: {
    width: '100%',
  },
  priceField: {
    marginTop: '10px',
  },
  productWrapper: {
    display: 'grid',
    gridGap: '10px',
    paddingTop: '0.8em',
    gridTemplateAreas: '"productProperty productValue"',
    gridTemplateColumns: '1fr 2fr',
  },
  productProperty: {
    color: theme.palette.text.secondary,
    gridArea: '"productProperty"',
  },
  productValue: {
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'space-between',
    gridArea: '"productsValue"',
    '& p': {
      lineHeight: 1.2,
    },
    '& p:nth-of-type(2)': {
      color: '#4CAF50',
    },
  },
  productImg: {
    width: '80px',
  },
  productContainer: {
    display: 'flex',
    justifyContent: 'space-between',
  },
  productContainerText: {
    width: '60%',
  },
  product: {
    padding: '24px 22px',
    border: `2px solid ${theme.palette.divider}`,
    borderBottom: 'none',
    width: '100%',
    boxSizing: 'border-box',
    position: 'relative',
    '&:last-child': {
      borderBottom: `2px solid ${theme.palette.divider}`,
    },
  },
  deleteButton: {
    top: '2px',
    right: '2px',
    position: 'absolute',
  },
  priceWas: {
    display: 'flex',
    justifyContent: 'flex-start',
    fontSize: '12px',
    color: theme.palette.text.secondary,
  },
  hidden: {
    color: 'transparent',
  },
  totalPrice: {
    width: '100%',
    textAlign: 'right',
  },
  bottom: {
    borderTop: '2px solid #D4D6D8',
  },
}));

export default AddProductItems;
