import * as React from 'react';
import {
  forwardRef,
  useContext,
  useRef,
  useCallback,
  useMemo,
  MouseEvent,
  KeyboardEvent,
  CSSProperties,
  useEffect,
} from 'react';
import { stylesheet } from 'typestyle';
import DOMPurify from 'dompurify';
import { StoreContext } from '../../../../../../../services/store';
import { CustomProductButtons, IMedia, IProduct } from '../../../../../../../types';
import { onKeyDownEventCallback } from '../../../../../../../utils/onKeyDown';
import useBorderRadius from '../../../../../../../hooks/useBorderRadius';
import formatCurrency from '../../../../../../../utils/formatCurrency';
import ProductImage from '../../../components/ProductImage';
import AddToCartIcon from '../../../../../../Icons/AddToCart';

const MIN_HEIGHT = 100;

interface ProductProps {
  product: IProduct;
  parentMedia: IMedia;
  isVisible: boolean;
  containerHeight: number;
  isSingleSection?: boolean;
  onAddToCart?: (product: IProduct, media: IMedia) => void;
}

const ProductModalItem = forwardRef<HTMLAnchorElement, ProductProps>(
  ({ product, parentMedia, isVisible, containerHeight, isSingleSection, onAddToCart }, ref) => {
    const context = useContext(StoreContext);
    const localAnchorRef = useRef<HTMLAnchorElement | null>(null);

    const ITEM_MAX_SIZE = Math.min(
      Math.max(containerHeight * (isSingleSection ? 0.5 : 0.65), 60),
      250,
    );

    const imageWidth = context.getProductImageWidth(product.id);
    const borderRadius = useBorderRadius(
      ITEM_MAX_SIZE,
      ITEM_MAX_SIZE,
      context.data.settings.thumbnail_corners,
    );

    const title = [product.title, product.variant_name].filter(Boolean).join(' - ');
    const imageLink = isVisible ? product.image_link : undefined;

    // Trigger productViewed event on mount and whenever the viewed post changes
    useEffect(() => {
      if (context.post && isVisible) {
        context.triggerEvent(
          'productViewed',
          {
            post: context.post,
            product: product.id,
          },
          context.data.id,
        );
      }
    }, [context.post?.id]);

    const handleShopClick = useCallback(
      (e: MouseEvent | KeyboardEvent) => {
        if (context.post) {
          context.triggerEvent(
            'productClicked',
            {
              post: context.post,
              originalEvent: e.nativeEvent,
              product: product.id,
            },
            context.data.id,
          );
        }

        setTimeout(() => {
          if (context.config.shopThisLookHandler) {
            context.config.shopThisLookHandler({ media: parentMedia, product }, product.link);
          } else {
            window.open(product.link, '_self');
          }
        }, 300);
      },
      [product, parentMedia, context],
    );

    const handleImageClick = useCallback(() => {
      localAnchorRef.current?.click();
    }, []);

    const customButtons = useMemo(() => (context.config.getCustomProductButtons
      ? Object.entries(context.config.getCustomProductButtons(React, product, parentMedia)).map(
        ([position, Button]) => (
          <div
            key={position}
            className={styles.buttonPositions[position as keyof CustomProductButtons]}
          >
            <Button onClick={() => {}} />
          </div>
        ),
      )
      : undefined), [context.config.getCustomProductButtons, product.id, parentMedia.id]);

    return (
      <a
        ref={(node) => {
          localAnchorRef.current = node;
          if (typeof ref === 'function') {
            ref(node);
          }
        }}
        href={product.link}
        style={styles.product(imageWidth, ITEM_MAX_SIZE)}
        className={`${context.config.classPrefix}-postviewer-details-product`}
        onClick={(e) => {
          e.preventDefault();
          handleShopClick(e);
        }}
        onKeyDown={(e) => onKeyDownEventCallback(e, () => handleShopClick(e))}
        aria-label={
          `Open product page for ${title}${product.price && product.currency
            ? `. Price: ${formatCurrency(product.price, product.currency)}`
            : ''}`}
        target='_self'
      >
        <div style={styles.imageWrapper}>
          <ProductImage
            containerHeight={ITEM_MAX_SIZE * 0.7}
            imageLink={imageLink}
            title={title}
            cornerType={context.data.settings.thumbnail_corners}
            borderRadius={borderRadius}
            onImageClick={handleImageClick}
            customButtons={customButtons}
            productId={product.id}
            mode='modal'
            isFocusable={false}
          />
          {context.config.addToCartHandler ? (
            <button
              type='button'
              style={styles.addToCartBtn}
              onClick={(e) => {
                e.preventDefault();
                e.stopPropagation();
                onAddToCart?.(product, parentMedia);
              }}
              aria-label={`Add ${title} to cart`}
              className={`${context.config.classPrefix}-add-to-cart`}
            >
              {context.config.addToCartIcon ? (
                <span aria-hidden='true'
                dangerouslySetInnerHTML={
                  { __html: DOMPurify.sanitize(context.config.addToCartIcon) }
                } />
              ) : (
                <AddToCartIcon
                size={isSingleSection
                  ? 'medium'
                  : 'compact'}
                enabled={true} showCircle={false} aria-hidden='true' />
              )}
            </button>
          ) : null}
        </div>

        <div style={styles.productInfo(context.isMobile)}>
          <h3 style={styles.heading}>
            <span style={styles.title}>{title}</span>
          </h3>
          {product.price !== undefined && product.price > 0 && product.currency ? (
            <p style={styles.price(context.isMobile)}>
              {formatCurrency(product.price, product.currency)}
            </p>
          ) : null}
        </div>
      </a>
    );
  },
);

const styles = {
  product: (width: number, itemMaxSize: number): CSSProperties => ({
    padding: '8px 8px 8px 0',
    marginTop: 8,
    display: 'flex',
    flexDirection: 'column' as const,
    width: width || 'fit-content',
    minHeight: MIN_HEIGHT,
    maxWidth: itemMaxSize,
    textDecoration: 'none',
    color: 'inherit',
    cursor: 'pointer',
  }),
  productInfo: (isMobile: boolean): CSSProperties => ({
    display: 'flex',
    flexDirection: 'column',
    fontWeight: 300,
    fontSize: isMobile ? 14 : 16,
    color: 'black',
    margin: '6px 0 0',
    flex: 1,
    minHeight: 0,
  }),
  heading: {
    margin: 0,
    fontSize: 'inherit',
    fontWeight: 'inherit',
  },
  title: {
    wordBreak: 'break-word',
    display: '-webkit-box',
    WebkitLineClamp: 2,
    WebkitBoxOrient: 'vertical',
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    margin: '0 0 4px 0',
    lineHeight: 1.2,
    color: 'black',
    textDecoration: 'none',
  },
  price: (isMobile: boolean): CSSProperties => ({
    margin: 0,
    fontSize: isMobile ? 12 : 14,
    whiteSpace: 'nowrap',
    overflow: 'hidden',
    textOverflow: 'ellipsis',
  }),
  imageWrapper: {
    position: 'relative',
    display: 'flex',
  } as CSSProperties,
  addToCartBtn: {
    position: 'absolute',
    bottom: 4,
    right: 4,
    background: 'rgba(255, 255, 255, 0.15)',
    backdropFilter: 'blur(8px)',
    WebkitBackdropFilter: 'blur(8px)',
    border: 'none',
    borderRadius: '50%',
    padding: 2,
    cursor: 'pointer',
    display: 'flex',
    alignItems: 'center',
    flexShrink: 0,
    transition: 'opacity 0.2s',
  } as CSSProperties,
  buttonPositions: stylesheet({
    topRight: { position: 'absolute', top: 0, right: 0 },
    topLeft: { position: 'absolute', top: 0, left: 0 },
    bottomRight: { position: 'absolute', bottom: 0, right: 0 },
    bottomLeft: { position: 'absolute', bottom: 0, left: 0 },
  }),
} as const;

export default ProductModalItem;
