"use client";

import React, { forwardRef } from "react";
import { getLabelSizeBasedOnButtonSize, sizeToClassNames } from "./helpers";

import {
  AnimationWrapper,
  DEFAULT_BUTTON_ANIMATION_TYPE,
} from "@shared/components/animation-wrapper";
import {
  ButtonProps,
  ButtonVariantsT,
} from "@shared/components/brand-button/types";
import { MaterialIcon } from "@shared/components/material-icon";
import { cx } from "@shared/utils";

// BrandButton is intentionally limited to prevent over-configuration, restricting className and children props.
export const BrandButton = forwardRef<
  HTMLButtonElement | HTMLAnchorElement,
  ButtonProps
>(
  (
    {
      variant = "primary_brand",
      isLoading = false,
      text,
      label,
      disabled,
      fullWidth,
      buttonClassName,
      size = { base: "medium" },
      iconName,
      iconSize = 24,
      iconFill = 0,
      // `disableAnimation` is intentionally NOT defaulted to `false` here.
      // Animations are opt-in by design: when this prop is left undefined,
      // AnimationWrapper falls back to its own default of `true` (animation
      // disabled). This keeps behavior consistent with the CMS contract where
      // an unset value means "no animation". Animation runs only when a caller
      // (or Contentful) explicitly passes `disableAnimation={false}`.
      disableAnimation,
      animationType = DEFAULT_BUTTON_ANIMATION_TYPE,
      as = "button",
      ...props
    },
    ref
  ) => {
    const getVariantClasses = () => {
      const baseClasses = cx(
        sizeToClassNames(size),
        "rounded-button pl-15 pr-15 inline-flex gap-2 items-center justify-center outline-none focus:outline focus:outline-2 focus:outline-offset-2 cursor-pointer transition-colors duration-200 align-top sm:whitespace-nowrap",
        fullWidth ? "w-full" : "w-auto"
      );

      const variantClasses: Record<ButtonVariantsT, string> = {
        primary_brand:
          "bg-bg-fill-brand text-text-brand-on-bg-fill [&:not(:disabled)]:hover:bg-bg-fill-brand-hover focus:outline-bg-fill-brand disabled:bg-bg-fill-brand-disabled",
        primary_inverse:
          "bg-bg-fill-inverse text-text-inverse [&:not(:disabled)]:hover:bg-bg-fill-inverse-hover focus:outline-bg-fill-inverse disabled:bg-bg-fill-inverse-disabled",
        secondary:
          "border border-border-secondary-on-bg-fill bg-bg-fill-secondary text-text [&:not(:disabled)]:hover:bg-bg-fill-secondary-hover focus:bg-bg-fill-secondary focus:outline-input-border-hover disabled:bg-bg-fill-secondary",
      };
      const stateClasses = cx(
        (disabled || isLoading) && "cursor-not-allowed",
        isLoading && "pl-7"
      );

      return cx(
        baseClasses,
        variantClasses[variant] || "",
        stateClasses,
        buttonClassName
      );
    };

    const variantClasses = getVariantClasses();

    let infoClassNames = `button--${variant}`;
    if (isLoading) infoClassNames += " button--loading";
    if (disabled) infoClassNames += " button--disabled";

    const combinedClassName = `${infoClassNames} ${variantClasses}`;

    const contentEl = (
      <>
        {isLoading ? (
          <MaterialIcon name="progress_activity" className="animate-spin" />
        ) : null}

        {label ? (
          <span className="flex flex-col">
            <span className={cx(getLabelSizeBasedOnButtonSize(size))}>
              {label}
            </span>
            {text}
          </span>
        ) : (
          text
        )}

        {iconName ? (
          <MaterialIcon
            name={iconName}
            size={iconSize}
            fill={iconFill}
            weight="200"
          />
        ) : null}
      </>
    );

    if (as === "a") {
      return (
        <AnimationWrapper
          disableAnimation={disableAnimation}
          animationType={animationType}
        >
          <a
            ref={ref as React.Ref<HTMLAnchorElement>}
            className={cx(combinedClassName)}
            {...(props as React.AnchorHTMLAttributes<HTMLAnchorElement>)}
            data-component="BrandButton"
            data-variant={"anchor"}
          >
            {contentEl}
          </a>
        </AnimationWrapper>
      );
    }

    return (
      <AnimationWrapper
        disableAnimation={disableAnimation}
        animationType={animationType}
      >
        <button
          ref={ref as React.Ref<HTMLButtonElement>}
          className={cx(combinedClassName)}
          disabled={disabled || isLoading}
          {...(props as React.ButtonHTMLAttributes<HTMLButtonElement>)}
          data-component="BrandButton"
          data-variant={"button"}
        >
          {contentEl}
        </button>
      </AnimationWrapper>
    );
  }
);

BrandButton.displayName = "BrandButton";

export type {
  ButtonProps,
  ButtonVariantsT,
  ButtonSizeT,
  ResponsiveSize,
} from "./types";
