import React, { useState, useEffect, useRef } from "react";
import classNames from "classnames";
import styles from "./ProductNavigation.module.css";

import { filterAttrs } from "@arc-ui/community-utils/filter-attrs";

import { useMediaQuery } from "@arc-ui/components/use-media-query";
import { ArcSizeBreakpointsS } from "@arc-ui/tokens-arc";

import { SectionHeading, type SectionHeadingProps } from "../SectionHeading";
import { type ListProps } from "./types";
import { ButtonV2 } from "@arc-ui/components/ButtonV2";
import { InformationCard } from "@arc-ui/components/InformationCard";
import { VerticalSpace } from "@arc-ui/components/VerticalSpace";
import { VisuallyHidden } from "@arc-ui/components/VisuallyHidden";

/**
 * Use `ProductNavigation` to give a collection of product information cards collected within a grid that has optional show/hide capability
 */
export const ProductNavigation: React.FC<ProductNavigationProps> = ({
  heading,
  id,
  headingLevel,
  isHeadingWordWrap,
  content,
  hideButton = false,
  productList,
  defaultExpanded = false,
  minHeight,
  cardsToDisplay = 3,
  listIncrement = 6,
  onClickMore,
  onClickLess,
  hideShowLess = false,
  isLoading,
  image,
  ...props
}) => {
  const [hideLessButton, setHideLessButton] = useState(false);
  const [skipLinkCard, setSkipLinkCard] = useState(cardsToDisplay);
  const [displayList, setDisplayList] = useState(
    productList.slice(0, cardsToDisplay),
  );
  const [displaySkipButton, setDisplaySkipButton] = useState(false);
  const cardRef = useRef<HTMLLIElement>(null);

  useEffect(() => {
    if (defaultExpanded) {
      setDisplayList(productList);
    }
  }, []);

  const moveFocus = () => {
    cardRef.current?.focus();
  };

  const clickController = () => {
    setDisplaySkipButton(true);
    // show more / current list length + increment
    if (displayList.length < productList.length) {
      if (onClickMore) onClickMore();
      setSkipLinkCard(displayList.length);
      setDisplayList(productList.slice(0, displayList.length + listIncrement));
    }
    // show less / reset to original list length
    else {
      if (onClickLess) onClickLess();
      setSkipLinkCard(cardsToDisplay);
      setDisplayList(productList.slice(0, cardsToDisplay));
    }

    // hide "show less" button option when fully expanded
    if (
      hideShowLess &&
      displayList.length + listIncrement >= productList.length
    ) {
      setHideLessButton(true);
    }
  };

  const isMinWidthArcBreakpointS = useMediaQuery(
    `(min-width: ${ArcSizeBreakpointsS})`,
  );

  return (
    <div {...filterAttrs(props)}>
      <SectionHeading
        isPadded
        id={id}
        data-testid="ProductNavigation-header"
        heading={heading}
        headingLevel={headingLevel}
        isHeadingWordWrap={isHeadingWordWrap}
        content={content}
        image={image}
      />
      <ul className={classNames(styles["product-navigation-grid"])}>
        {displayList?.map((cardProps, i) => (
          <li
            key={`displayList-${i}`}
            tabIndex={-1}
            ref={i === skipLinkCard ? cardRef : undefined}
            data-cy={`list-item-${i}`}
          >
            <InformationCard
              {...cardProps}
              minHeight={minHeight ?? cardProps.minHeight}
              headingLevel={cardProps.headingLevel ?? "2"}
            />
          </li>
        ))}
      </ul>
      {!hideButton &&
        !(defaultExpanded && displayList.length === productList.length) && (
          <>
            <VerticalSpace size="40" />
            <div style={{ display: "flex" }}>
              {!hideLessButton && (
                <ButtonV2
                  label={
                    displayList.length < productList.length
                      ? "Show more"
                      : "Show less"
                  }
                  buttonStyle="secondary"
                  onClick={clickController}
                  isFullWidth={isMinWidthArcBreakpointS ? false : true}
                  isLoading={isLoading}
                />
              )}
              {displaySkipButton && displayList.length > cardsToDisplay && (
                <div
                  id="skip-link"
                  className={classNames(styles["productNavigation-skipLink"])}
                  tabIndex={-1}
                >
                  <ButtonV2
                    label="Move to first new card"
                    buttonStyle="primary"
                    onClick={moveFocus}
                    isFullWidth={isMinWidthArcBreakpointS ? false : true}
                  />
                </div>
              )}
              <VisuallyHidden>
                <div aria-live="polite" id="aria-live-region" aria-atomic>
                  <p>
                    Total products listed {displayList.length}. Total products
                    hidden {productList.length - displayList.length}.
                  </p>
                </div>
              </VisuallyHidden>
            </div>
          </>
        )}
    </div>
  );
};

export interface ProductNavigationProps
  extends Omit<SectionHeadingProps, "isPadded"> {
  /**
   * List items for `ProductNavigation`.
   */
  productList: ListProps[];
  /**
   * Hide "show more" or "show less" button controls.
   */
  hideButton?: boolean;
  /**
   * Prevent "show less" button from appearing after full productList is displayed.
   */
  hideShowLess?: boolean;
  /**
   * Set default expand or collapse view of product on page load.
   */
  defaultExpanded?: boolean;
  /**
   * Set number of products to hide or show.
   */
  listIncrement?: number;
  /**
   * Set number of products to show by default.
   */
  cardsToDisplay?: number;
  /**
   * Custom onClick handler called everytime "show more" is pressed
   */
  onClickMore?: () => void;
  /**
   * Custom onClick handler called everytime "show less" is pressed
   */
  onClickLess?: () => void;
  /**
   * Set a loading state for the "show more" and "show less" buttons
   */
  isLoading?: boolean;
  /**
   * Set minHeight for all products.
   */
  minHeight?: number;
}
