import React from "react";
import { Button } from "../button";
import BlogCard from "../cards/blog-card";
import FloatingImageCard from "../cards/floating-image-card";
import FullImageCard from "../cards/full-image-card";
import SimpleCard from "../cards/simple-card";
import { CalloutCardType, CalloutItem, CalloutProps } from "./types";

import { AnimationWrapper } from "@shared/components/animation-wrapper";
import { Text } from "@shared/components/text";
import { cx } from "@shared/utils";

const backgroundClassMap: Record<string, string> = {
  cream500: "bg-[#FFFEEF]",
  gray100: "bg-fill-secondary",
  white: "bg-white",
  transparent: "",
  blue: "bg-fill-brand",
  green: "bg-fill-brand-accent",
  navy: "bg-fill-inverse",
  purple: "bg-fill-brand-tertiary",
  yellow: "bg-[#F5FF1E]",
};

// Literal class strings (Tailwind JIT only picks up literal tokens; do not
// build these by concatenation at runtime).
// Per-card responsive width classes for the flex-wrap layout. Mobile is
// always full-width; md renders 1 or 2 columns; lg renders up to 6.
// The calc() values subtract a portion of the gap so cards fit cleanly.
const mdWidthMap: Record<number, string> = {
  1: "md:w-full",
  2: "md:w-[calc(50%-1rem)]",
};
const lgWidthMap: Record<number, string> = {
  1: "lg:w-full",
  2: "lg:w-[calc(50%-0.75rem)]",
  3: "lg:w-[calc(33.333%-1rem)]",
  4: "lg:w-[calc(25%-1.125rem)]",
  5: "lg:w-[calc(20%-1.2rem)]",
  6: "lg:w-[calc(16.666%-1.25rem)]",
};

/**
 * Mirrors the local @ui Callout `calculateOptimalColumns` logic:
 *   - ≤4 cards: one per column
 *   - divisible by 3: 3 cols
 *   - divisible by 4: 4 cols
 *   - >6 cards: 4 cols
 *   - else: 3 cols
 */
const calculateOptimalColumns = (count: number): number => {
  if (count <= 4) return count || 1;
  if (count % 3 === 0) return 3;
  if (count % 4 === 0) return 4;
  if (count > 6) return 4;
  return 3;
};

const clampCol = (n: number) => Math.max(1, Math.min(6, n));

export const Callout: React.FC<CalloutProps> = ({
  anchorId,
  title,
  items,
  enableHeading = false,
  subtitle,
  description,
  finePrint,
  cta,
  color = "dark",
  maxWidth = true,
  maxCardsPerRow,
  cardType = "simple",
  backgroundColor,
  background,
  textColor,
  containerClassName,
  innerClassName,
  applyBoxShadow = false,
  cardStackingMobile = true,
  cardsWidth = true,
  noGutter = false,
  disableAnimation,
  animationType = "lift",
}) => {
  const itemCount = items?.length ?? 0;
  const desktopCols = clampCol(
    maxCardsPerRow ?? calculateOptimalColumns(itemCount)
  );
  const lgCols = clampCol(Math.min(desktopCols, itemCount || desktopCols));

  // Layout selection:
  //   - cardsWidth === false  → explicit vertical stack (single column)
  //   - any other value (true / undefined / string / etc.) → legacy
  //     flex-wrap layout that always renders multi-column on md+ and
  //     full-width on mobile. This matches the pre-0.1.79 DOM and keeps
  //     consumers like SMB-browse rendering correctly without changes.
  const isStackMode = cardsWidth === false && cardType !== "blog";
  const gridClass = isStackMode
    ? cx(
        "flex flex-col items-stretch self-stretch",
        noGutter ? "gap-0" : "gap-6"
      )
    : cx(
        "flex flex-wrap items-stretch justify-center self-stretch",
        noGutter ? "gap-0" : "gap-6",
        noGutter ? "md:gap-0" : "md:gap-6"
      );

  // Per-card width classes — only used for flex-wrap layout. Mobile is
  // full-width; md respects `cardStackingMobile` (1 col when true, 2 cols
  // when false); lg uses the optimal column count. Stack mode skips this.
  const cardWidthClass = isStackMode
    ? ""
    : cx(
        "w-full",
        mdWidthMap[clampCol(cardStackingMobile ? 1 : Math.min(2, desktopCols))],
        lgWidthMap[lgCols]
      );

  const renderCard = (item: CalloutItem, index: number) => {
    const itemCardType: CalloutCardType = item.cardType ?? cardType;

    // Stack mode preserves any legacy lgWidth/mdWidth on the card itself;
    // flex-wrap mode controls width via the wrapper div, so strip them.
    const widthProps = isStackMode
      ? { lgWidth: undefined, mdWidth: undefined }
      : {};

    switch (itemCardType) {
      case "blog": {
        const blogItem = item as any;
        return (
          <BlogCard
            key={index}
            title={blogItem.title}
            href={blogItem.slug}
            description={blogItem.shortDescription}
            date={blogItem.blogCreationDate}
            category={blogItem.category}
            image={blogItem.cover}
            asGrid={false}
            {...widthProps}
          />
        );
      }
      case "fullImage":
        return (
          <FullImageCard
            key={index}
            card={{
              ...(item as any),
            }}
            {...widthProps}
          />
        );
      case "floatingImage":
        return (
          <FloatingImageCard
            key={index}
            card={{
              ...(item as any),
            }}
            {...widthProps}
          />
        );
      case "simple":
      default:
        return (
          <SimpleCard
            key={index}
            card={{
              ...(item as any),
              shadow: (item as any).shadow ?? applyBoxShadow,
            }}
            {...widthProps}
          />
        );
    }
  };

  const sectionStyle = background ? { background } : undefined;
  const headingStyle = textColor ? { color: textColor } : undefined;
  const sectionBgClass = background
    ? ""
    : backgroundColor
      ? (backgroundClassMap[backgroundColor] ?? "")
      : "";

  return (
    <section
      id={anchorId}
      className={cx("component-container", sectionBgClass, containerClassName)}
      style={sectionStyle}
    >
      <div
        className={cx(
          noGutter ? "p-0" : "mx-5 mb-5 mt-12 md:mx-0 md:mb-0 md:mt-0 md:px-6 md:pb-8 md:pt-16 lg:px-0 lg:py-20",
          maxWidth && "max-w-120 xl:mx-auto",
          color === "dark" ? "text-text" : "text-white",
          innerClassName
        )}
      >
        <div className="callout-container flex flex-col gap-10 md:gap-16">
          <div className="title-holder" style={headingStyle}>
            {title && (
              <Text
                as={enableHeading ? "h1" : "h2"}
                className="heading2 md:heading1 md:text-center"
              >
                {title}
              </Text>
            )}
            {subtitle && (
              <Text
                as={enableHeading ? "h2" : "h3"}
                className="subheading3 mt-2 md:subheading1 md:text-center lg:mt-3"
              >
                {subtitle}
              </Text>
            )}
            {description && (
              <Text as="p" className="body1 mt-4 text-center md:mt-6">
                {description}
              </Text>
            )}
          </div>
          <div className={cx("card-holder", gridClass)}>
            {items.map((item, index: number) =>
              isStackMode ? (
                <AnimationWrapper
                  key={`callout-card-${index}`}
                  animationType={animationType}
                  disableAnimation={disableAnimation}
                >
                  {renderCard(item, index)}
                </AnimationWrapper>
              ) : (
                <div
                  key={`callout-card-${index}`}
                  className={cx("callout-card", cardWidthClass)}
                >
                  <AnimationWrapper
                    animationType={animationType}
                    disableAnimation={disableAnimation}
                  >
                    {renderCard(item, index)}
                  </AnimationWrapper>
                </div>
              )
            )}
          </div>
          {(cta || finePrint) && (
            <div className="flex flex-col items-center gap-4">
              {cta ? (
                <Button
                  linkClassName="label1"
                  buttonClassName="label1"
                  {...cta}
                >
                  {cta.label ?? cta.buttonLabel}
                </Button>
              ) : null}
              {finePrint ? (
                <Text as="div" className="footnote text-center text-text">
                  {finePrint}
                </Text>
              ) : null}
            </div>
          )}
        </div>
      </div>
    </section>
  );
};

export default Callout;
