import cx from "classnames";
import React from "react";

import { formatPrice } from "../../utils/helpers";
import { Button } from "../Button";
import { Container } from "../Container";
import { Grid, GridCol } from "../Grid";
import { Image } from "../Image";
import { Sticker } from "../Sticker";

export type HeroTextSize = "medium" | "large";
export type StickerColor = "black" | "orange";

export interface HeroImageSrc {
  src: string;
  srcSet?: string;
}

export interface HeroImageResponsive {
  default: string;
  sm?: string;
  lg?: string;
  xl?: string;
  xxl?: string;
  [key: string]: string | undefined;
}

export type HeroImage = HeroImageSrc | HeroImageResponsive;

export interface HeroPriceObject {
  amount: number;
  prefix?: React.ReactNode;
  suffix?: React.ReactNode;
}

export type HeroPrice = string | HeroPriceObject;

export interface HeroButtonProps {
  children: React.ReactNode;
  [key: string]: any;
}

export interface HeroStickerProps {
  color?: StickerColor;
  children?: React.ReactNode;
  className?: string;
}

export interface HeroProps {
  /** Action button props */
  button?: HeroButtonProps;
  /** Main text */
  description?: React.ReactNode;
  hasFullwidthImage?: boolean;
  /** Gradient overlay ensures proper text readability */
  hasGradientOverlay?: boolean;
  /** Use svg illustrations, png for product images and jpg for photos */
  image?: HeroImage;
  price?: HeroPrice;
  sticker?: HeroStickerProps;
  /** Adjust title and description size. Medium sets display-2 title and 18px text, large uses display-1 title and 20px text.  */
  textSize?: HeroTextSize;
  /** Hero title */
  title: string;
}

const textSizes = {
  medium: {
    title: "h2",
    description: "bold",
  },
  large: {
    title: "h1",
    description: "large bold",
  },
} as const;

export const Hero: React.FC<HeroProps> = ({
  button,
  description,
  hasGradientOverlay,
  image,
  hasFullwidthImage,
  price,
  sticker,
  title,
  textSize = "medium",
}) => {
  const hasSingleImage = image
    ? ("src" in image && !!image.src) ||
      ("default" in image && image.default && Object.keys(image).length === 1)
    : false;

  const className = cx("hero");
  return (
    <div className={className}>
      <Container>
        <Grid className="justify-content-space-between">
          <GridCol
            size={{
              sm: 10,
              md: 9,
              lg: 5,
            }}
            className="hero__content"
          >
            <h1 className={textSizes[textSize].title}>{title}</h1>
            {description && (
              <p
                className={cx(
                  textSizes[textSize].description,
                  "hero__description",
                )}
              >
                {description}
              </p>
            )}
            {price && (
              <p className="h2 hero__price">
                {typeof price === "string" && price}
                {typeof price === "object" && (
                  <>
                    {price.prefix}
                    {formatPrice(price.amount)}
                    {price.suffix}
                  </>
                )}
              </p>
            )}
            {button && <Button type="primary" {...button} />}
          </GridCol>
          {sticker && (
            <GridCol
              size={{
                md: 3,
                lg: 2,
              }}
              className="hero__content show-md"
            >
              <Sticker
                {...sticker}
                className={cx("hero__sticker", sticker.className)}
              />
            </GridCol>
          )}
          {image && (
            <div className="hero__image-wrapper">
              <Image
                src={"src" in image ? { default: image.src } : (image as any)}
                srcSet={"src" in image ? image.srcSet : undefined}
                alt=""
                className={cx("hero__image", {
                  "hero__image--fullwidth": hasFullwidthImage,
                  "hero__image--single": hasSingleImage,
                  "hero__image--gradient": hasGradientOverlay,
                  "hero__image--gradient-halfwidth":
                    hasGradientOverlay && !hasFullwidthImage,
                })}
              />
            </div>
          )}
        </Grid>
      </Container>
    </div>
  );
};

Hero.displayName = "Hero";
