import * as React from 'react';
import { Utils } from '../Utils';
import { DataContext } from '@assets/js-shop/context';
import { translate as _t } from '@assets/js-shop/ShopUtils';
import { ICartItem } from '@assets/js-shop/GraphQLInterfaces';
import { GtmUtils } from '@assets/js-shop/cart/GtmUtils';
import { CartItemPhoto } from '@assets/js-shop/cart/cartBody/CartItemPhoto';
import config from '@assets/js-shop/config';
import { IShopDataContext } from '@assets/js-shop/Interfaces';
import { Icon } from '@assets/shared/icon/Icon';

interface CartItemProps {
   item: ICartItem;
   onChange: (e: React.MouseEvent<HTMLButtonElement> | React.ChangeEvent, item: ICartItem, offset: number) => void;
   isLastAdded: boolean;
}

interface CartItemState {
   edit: boolean;
   value: string;
}

export class CartItem extends React.PureComponent<CartItemProps, CartItemState> {
   static contextType = DataContext;
   declare context: React.ContextType<typeof DataContext>;
   private productRef: React.RefObject<HTMLDivElement>;
   private scrollTimeout: NodeJS.Timeout;

   public state = {
      edit: false,
      value: '',
   };

   constructor(props: CartItemProps) {
      super(props);
      this.productRef = React.createRef();

      this.renderDelete = this.renderDelete.bind(this);
      this.renderBuyCount = this.renderBuyCount.bind(this);
   }

   componentDidUpdate() {
      if (this.props.item.product && this.props.isLastAdded) {
         // timeout resi problemy s nefunkcnim scrollem nahoru
         this.scrollTimeout = setTimeout(() => {
            this.productRef.current.scrollIntoView({
               behavior: 'smooth',
               block: 'nearest',
            });
         }, 50);
      }
   }

   componentWillUnmount() {
      clearTimeout(this.scrollTimeout);
   }

   render() {
      const item = this.props.item;

      return (
         <div
            className={`cartbox-product ${item.product ? '' : 'product-loading'}`}
            ref={this.productRef}>
            <CartItemPhoto item={item} />

            <div className="product-content">
               {item.product ? (
                  <>
                     <div className="product-title">
                        {this.props.isLastAdded && (
                           <p className="item-added-info">
                              <Icon icon="CheckCircle" /> {_t('itemAddedToCart')}
                           </p>
                        )}
                        {this.printTitle(item)}
                        {config.showProductAvailability ? this.renderAvailability(item) : ''}
                        {this.renderPrice(item)}
                     </div>
                     <div className="buy-count-wrapper">{this.renderBuyCount(item)}</div>
                  </>
               ) : (
                  <p className="product-title">{item.name}</p>
               )}
            </div>
            {item.product && this.renderDelete(item)}
         </div>
      );
   }

   protected printTitle(item: ICartItem) {
      return <p>
         <a href={item.product.url} {...GtmUtils.getProductClickAttributes(item)}>{item.product.title}</a>
         {item.product.variationTitle && <span>{item.product.variationTitle}</span>}
         {item.printNote && <small>{item.printNote}</small>}
      </p>;
   }

   protected renderPrice(item: ICartItem): JSX.Element {
      return (
         <div className="price-total">
            {item.discount >= 1 ? (
               <span className="flag flag-discount">{Utils.printDiscount(item.discount)}</span>
            ) : (
               ''
            )}

            <div>
               {item.discount >= 1 ? (
                  <span>
                     {Utils.printPrice(item.priceOriginal, this.context as IShopDataContext)}
                  </span>
               ) : (
                  ''
               )}
               <strong>{Utils.printPrice(item.price, this.context as IShopDataContext)}</strong>
            </div>
         </div>
      );
   }

   protected renderAvailability(item: ICartItem): JSX.Element {
      return (
         <p className={item.product.inStore > 0 ? 'delivery delivery-0' : 'delivery delivery--1'}>
            {item.product.inStore > 0 ? _t('skladem') : _t('není skladem')}
         </p>
      );
   }

   protected renderDelete(item: ICartItem): JSX.Element {
      return (
         <button className='delete-product fc icons_trash'
                 onClick={(e: React.MouseEvent<HTMLButtonElement>) => this.props.onChange(e, item, -item.pieces)}
                 {...GtmUtils.getRemoveItemAttributes(item, item.pieces)}
         >{MODULES.COMPONENTS ? <i dangerouslySetInnerHTML={{ __html: require('@assets/icons/trash.svg?raw') }}/> : ''}</button>
      );
   }

   protected renderBuyCount(item: ICartItem): JSX.Element {
      return (
         <>
            <input
               className="form-control"
               type="number"
               name="No"
               min={item.step}
               step={item.step}
               title={_t('pocetKs')}
               value={this.state.edit ? this.state.value : item.pieces}
               onChange={this.handlePiecesInput}
               onFocus={() => this.setEditMode(true)}
               onBlur={() => this.setEditMode(false)}
            />
            <div className="buy_count">
               <button
                  type="button"
                  className="fc icons_caret-up plus"
                  title={`${_t('pridat')} ${item.step} ${_t('ks')}`}
                  onClick={(e: React.MouseEvent<HTMLButtonElement>) => this.props.onChange(e, item, +item.step)}
                  {...GtmUtils.getAddItemAttributes(item, 1)}
               >{MODULES.COMPONENTS ? <i className="c-icon" dangerouslySetInnerHTML={{ __html: require('@assets/icons/caret-up.svg?raw') }}/> : ''}</button>
               <button
                  type="button"
                  className="fc icons_caret-down minus"
                  title={`${_t('odebrat')} ${item.step} ${_t('ks')}`}
                  onClick={(e: React.MouseEvent<HTMLButtonElement>) =>
                     this.props.onChange(e, item, -item.step)
                  }
                  disabled={item.pieces <= item.step}
                  {...GtmUtils.getRemoveItemAttributes(item, 1)}
               >{MODULES.COMPONENTS ? <i className="c-icon" dangerouslySetInnerHTML={{ __html: require('@assets/icons/caret-down.svg?raw') }}/> : ''}</button>
            </div>
         </>
      );
   }

   protected handlePiecesInput = (e: React.ChangeEvent<HTMLInputElement>) => {
      if (this.state.edit) {
         const value = e.target.value;
         if (!Number.isNaN(parseFloat(value)) && parseFloat(value) > 0) {
            const pieces = Utils.roundToStep(parseFloat(value), this.props.item.step);
            this.props.onChange(e, this.props.item, pieces - this.props.item.pieces);
         }
         this.setState({ value });
      }
   };

   protected setEditMode(enable: boolean) {
      if (enable) {
         this.setState({ value: '' });
      }
      this.setState({ edit: enable });
   }
}
