import React, { forwardRef, Ref } from "react";
import classNames from "classnames";
import { createRocket } from "../_util/create-rocket";
import { StyledProps, InferProps } from "../_type";
import { forwardRefWithStatics } from "../_util/forward-ref-with-statics";
import { Justify } from "../justify";
import { useConfig } from "../_util/config-context";
import { H3 } from "../heading";

/**
 * 卡片组件 `<Card>` 属性集合。
 */
export interface CardProps extends StyledProps {
  /**
   * 卡片内容，可包含
   *
   * - `<Card.Header>` 卡片头部
   * - `<Card.Body>` 卡片主体
   * - `<Card.Footer>` 卡片底部
   */
  children?: React.ReactNode;

  /**
   * 是否显示为带边框样式
   */
  bordered?: boolean;

  /**
   * 是否铺满内容区
   *
   * - `false` - 不铺满
   * - `true` - 铺满（页面不包含顶部一级标题，即 `Layout.Content.Header`）
   * - `"withHeader"` - 铺满（页面包含顶部一级标题，即 `Layout.Content.Header`）
   */
  full?: boolean | "withHeader";
}

const CardHeader = createRocket("CardHeader", "div.@{prefix}-card__header");
const CardFooter = createRocket("CardFooter", "div.@{prefix}-card__footer");

/**
 * 卡片头部 `<Card.Header>` 属性集合。
 */
export interface CardHeaderProps extends InferProps<typeof CardHeader> {}

/**
 * 卡片主体 `<Card.Body>` 属性集合。
 */
export interface CardBodyProps extends StyledProps {
  /**
   * 内容标题（可选）
   */
  title?: React.ReactNode;

  /**
   * 内容小标题（可选）
   */
  subtitle?: React.ReactNode;

  /**
   * 操作区（可选）
   */
  operation?: React.ReactNode;

  /**
   * 内容
   */
  children?: React.ReactNode;
}

/**
 * 卡片底部 `<Card.Footer> 属性列表`
 */
export interface CardFooterProps extends InferProps<typeof CardFooter> {}

const CardBody = forwardRef(
  (props: CardBodyProps, ref: Ref<HTMLDivElement>) => {
    const { classPrefix } = useConfig();
    const { className, style, title, subtitle, operation, children } = props;

    return (
      <div
        ref={ref}
        className={classNames(`${classPrefix}-card__body`, className)}
        style={style}
      >
        {(title || subtitle || operation) && (
          <div className={`${classPrefix}-card__title`}>
            <Justify
              left={
                <H3>
                  {title}
                  {subtitle && (
                    <span className={`${classPrefix}-card__subtitle`}>
                      {subtitle}
                    </span>
                  )}
                </H3>
              }
              right={operation}
            />
          </div>
        )}
        <div className={`${classPrefix}-card__content`}>{children}</div>
      </div>
    );
  }
);

CardBody.displayName = "CardBody";

export const Card = forwardRefWithStatics(
  (
    { className, children, bordered, full, ...props }: CardProps,
    ref: Ref<HTMLDivElement>
  ) => {
    const { classPrefix } = useConfig();
    const cardClassName = classNames(
      `${classPrefix}-card`,
      {
        [`${classPrefix}-card--bordered`]: bordered,
        [`${classPrefix}-card--full`]: full === true,
        [`${classPrefix}-card--full-with-header`]: full === "withHeader",
      },
      className
    );
    return (
      <div ref={ref} className={cardClassName} {...props}>
        {children}
      </div>
    );
  },
  // Card statics
  {
    Header: CardHeader,
    Body: CardBody,
    Footer: CardFooter,
  }
);

Card.displayName = "Card";
