import React from "react";
import { ButtonProps } from "./types";

import {
  AnimationWrapper,
  DEFAULT_BUTTON_ANIMATION_TYPE,
} from "@shared/components/animation-wrapper";
import { BrandButton, ButtonVariantsT } from "@shared/components/brand-button";
import { Button as CoreButton } from "@shared/components/button";
import { Link } from "@shared/components/link";
import { MaterialIcon } from "@shared/components/material-icon";
import type { IconName } from "@shared/components/material-icon/types";
import { Text } from "@shared/components/text";
import { cx } from "@shared/utils";
import { buildPreservedQueryHref } from "@shared/utils/utm";

const textVariantClasses: Record<string, string> = {
  primary_brand: "text-text-brand",
  primary_inverse: "text-text",
  secondary: "text-text",
};

export const Button: React.FC<ButtonProps> = props => {
  const {
    showButtonAs = "solid",
    buttonVariant = "primary_brand",
    buttonLabel,
    buttonPrefix,
    href,
    target = "_blank",
    anchorId,
    linkClassName,
    linkVariant,
    fullWidth,
    preDefinedFunctionExecution,
    renderCheckPlans,
    buttonClassName,
    clickToOpen,
    tabmodalNameToOpen,
    idNameToOpen,
    onModalButtonClick,
    onClick,
    iconFill = 0,
    buttonIconName,
    buttonIconPosition,
    size,
    iconSize = 24,
    preserveQueryParameters,
    disableAnimation,
    animationType = DEFAULT_BUTTON_ANIMATION_TYPE,
    ...rest
  } = props;
  
  const isLeftIcon = buttonIconPosition === "left";
  const matIconName = buttonIconName as IconName | undefined;
  const brandButtonClassName = cx(
    buttonClassName,
    isLeftIcon && matIconName ? "flex-row-reverse" : ""
  );

  if (
    preDefinedFunctionExecution === "check availability" &&
    renderCheckPlans
  ) {
    const checkPlansNode = renderCheckPlans?.({
      ctaText: buttonLabel,
      buttonVariant: buttonVariant,
      showButtonAs: showButtonAs,
      cta: { ...props },
    });
    return React.isValidElement(checkPlansNode) ? (
      // `disableAnimation` is passed through as-is (not defaulted to `false`).
      // Animations are opt-in: when unset, AnimationWrapper falls back to its
      // default of `true` (disabled), matching the CMS contract where an unset
      // value means "no animation". This stays consistent with the other
      // branches in this block. Animation runs only when a caller explicitly
      // passes `disableAnimation={false}`.
      <AnimationWrapper
        disableAnimation={disableAnimation}
        animationType={animationType}
      >
        {checkPlansNode}
      </AnimationWrapper>
    ) : (
      checkPlansNode
    );
  }

  function handleClickId() {
    if (clickToOpen === "clickId" && idNameToOpen) {
      const element = document.getElementById(idNameToOpen);
      if (element) {
        element.scrollIntoView({
          behavior: "smooth",
          block: "start",
        });
        element.click?.();
      }
    }
  }

  function handleModalClick(
    event?: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>
  ) {
    if (clickToOpen === "modal") {
      // Prevent the anchor's href from navigating so the CTA only opens the modal.
      event?.preventDefault();
      onModalButtonClick?.(tabmodalNameToOpen);
    }
    if (clickToOpen === "clickId") {
      event?.preventDefault();
      handleClickId();
    }
  }

  function linkClick(event: React.MouseEvent<HTMLAnchorElement>) {
    handleModalClick(event);
    onClick?.(event);
  }

  function buttonClick(event: React.MouseEvent<HTMLButtonElement>) {
    handleModalClick(event);
    onClick?.(event);
  }

  // Resolve the final href — merge non-UTM query params when preserveQueryParameters is true
  const currentSearch =
    typeof window !== "undefined" ? window.location.search : "";
  const resolvedHref = preDefinedFunctionExecution
    ? undefined
    : href && preserveQueryParameters && currentSearch
      ? buildPreservedQueryHref(href, currentSearch)
      : href;
  let CTA = (
    <CoreButton onClick={buttonClick} className={buttonClassName} {...rest} />
  );

  switch (showButtonAs) {
    case "solid":
      CTA = resolvedHref ? (
        <BrandButton
          as="a"
          href={resolvedHref}
          id={anchorId}
          variant={buttonVariant}
          text={buttonLabel}
          label={buttonPrefix}
          fullWidth={fullWidth}
          buttonClassName={brandButtonClassName}
          size={size}
          onClick={linkClick}
          iconName={matIconName}
          iconSize={iconSize}
          iconFill={iconFill}
          disableAnimation={disableAnimation}
          animationType={animationType}
        />
      ) : (
        <BrandButton
          id={anchorId}
          variant={buttonVariant}
          text={buttonLabel}
          label={buttonPrefix}
          fullWidth={fullWidth}
          size={size}
          onClick={buttonClick}
          iconName={matIconName}
          iconSize={iconSize}
          iconFill={iconFill}
          buttonClassName={brandButtonClassName}
          disableAnimation={disableAnimation}
          animationType={animationType}
        />
      );
      break;
    case "text":
      CTA = (
        <Link
          title={buttonLabel}
          href={resolvedHref}
          target={target}
          variant={linkVariant || "default"}
          className={cx(
            matIconName &&
              "label1 inline-flex items-center gap-2 no-underline",
            textVariantClasses[buttonVariant],
            linkClassName
          )}
          onClick={linkClick}
        >
          {matIconName ? (
            <>
              {isLeftIcon ? (
                <MaterialIcon
                  name={matIconName as IconName}
                  size={iconSize}
                  fill={iconFill}
                />
              ) : null}
              {buttonLabel}
              {!isLeftIcon ? (
                <MaterialIcon
                  name={matIconName as IconName}
                  size={iconSize}
                  fill={iconFill}
                />
              ) : null}
            </>
          ) : (
            <>{buttonLabel}</>
          )}
        </Link>
      );
      break;
    case "button-with-icon":
      CTA = resolvedHref ? (
        <BrandButton
          as="a"
          href={resolvedHref}
          id={anchorId}
          variant={buttonVariant}
          text={buttonLabel}
          label={buttonPrefix}
          fullWidth={fullWidth}
          buttonClassName={brandButtonClassName}
          size={size}
          onClick={linkClick}
          iconName={matIconName}
          iconSize={iconSize}
          iconFill={iconFill}
          disableAnimation={disableAnimation}
          animationType={animationType}
        />
      ) : (
        <BrandButton
          id={anchorId}
          variant={buttonVariant}
          text={buttonLabel}
          label={buttonPrefix}
          fullWidth={fullWidth}
          buttonClassName={brandButtonClassName}
          size={size}
          onClick={buttonClick}
          iconName={matIconName}
          iconSize={iconSize}
          iconFill={iconFill}
          disableAnimation={disableAnimation}
          animationType={animationType}
        />
      );
      break;
    case "text-with-icon": {
      const getTextWithIconVariantClass = (
        variant: ButtonVariantsT
      ): string => {
        const variantMap: Record<ButtonVariantsT, string> = {
          primary_brand: "text-text-brand",
          primary_inverse: "text-text-inverse",
          secondary: "text-text",
        };
        return variantMap[variant] || "text-text-brand";
      };

      const textWithIconVariantClass =
        getTextWithIconVariantClass(buttonVariant);
      CTA = (
        <Link
          href={resolvedHref}
          target={target}
          onClick={linkClick}
          className={cx(
            "group mt-auto inline-flex items-center justify-start gap-2 pt-3 text-sm no-underline",
            textWithIconVariantClass,
            buttonClassName
          )}
          aria-label={buttonLabel}
        >
          {isLeftIcon && matIconName ? (
            <MaterialIcon
              name={matIconName as IconName}
              fill={iconFill}
              size={iconSize}
              weight="200"
            />
          ) : null}
          <Text aria-label={buttonLabel} className="label1 text-nowrap">
            {buttonLabel}
          </Text>
          {matIconName && !isLeftIcon && (
            <MaterialIcon
              name={matIconName as IconName}
              fill={iconFill}
              size={iconSize}
              weight="200"
            />
          )}
        </Link>
      );
      break;
    }
    case "unstyled": // For unstyled, we can use the CoreButton without any additional styling
      break;
    default: // For default, we can use the CoreButton without any additional styling
      break;
  }
  return (
    <AnimationWrapper
      disableAnimation={disableAnimation}
      animationType={animationType}
    >
      {CTA}
    </AnimationWrapper>
  );
};
export default Button;
