import React from "react";
import classNames from "classnames";
import { StyledProps } from "../_type";
import { FormControlProps, FormControl } from "./FormControl";
import { FormContext } from "./FormContext";
import { useConfig } from "../_util/config-context";
import { Bubble } from "../bubble";
import { Icon } from "../icon";

export interface FormItemProps extends StyledProps {
  /**
   * 表单项说明
   */
  label?: React.ReactNode;

  /**
   * 表单控件内容，可以容纳任意表单组件，如 Input, CheckGroup 等
   * 如果是只读表单内容，则可传入字符串
   */
  children?: React.ReactNode;

  /**
   * 控件和标签对齐方式
   *
   * - `auto` 自动根据传入的控件类型决定对齐方式
   * - `top` 增加间距以实现标签文本和控件内容顶部对齐
   * - `middle` 标签文本对齐到控件的中间
   *
   * @default "auto"
   */
  align?: "auto" | "top" | "middle";

  /**
   * 表单项状态
   */
  status?: FormControlProps["status"];

  /**
   * 是否展示 icon
   * @default true
   */
  showStatusIcon?: boolean;

  /**
   * 表单项提示信息/校验信息
   */
  message?: FormControlProps["message"];

  /**
   * 表单额外说明信息
   *
   * *可与 `message` 信息同时存在*
   * @since 2.6.8
   */
  extra?: FormControlProps["extra"];

  /**
   * 是否为必填项（样式）
   *
   * @default false
   */
  required?: boolean;

  /**
   * 是否展示表单项提示
   *
   * *图标气泡形式展示在 label 右侧*
   *
   * @since 2.6.8
   */
  tips?: React.ReactNode;

  /**
   * 表单控件后的装饰内容
   */
  suffix?: React.ReactNode;

  /**
   * HTML for 属性
   *
   * 包含 `label` 时生效
   */
  htmlFor?: string;
}

export const FormItem = React.forwardRef(function FormItem(
  {
    htmlFor,
    label,
    children,
    status,
    message,
    extra,
    align,
    required,
    tips,
    showStatusIcon = true,
    suffix,
    className,
    ...props
  }: FormItemProps,
  ref: React.Ref<HTMLDivElement>
) {
  const { classPrefix } = useConfig();
  return (
    <FormContext.Consumer>
      {({ hideLabel, fixedLabelWidth }) => (
        <div
          ref={ref}
          className={classNames(`${classPrefix}-form__item`, className)}
          {...props}
        >
          {!hideLabel && (
            <div
              className={classNames(`${classPrefix}-form__label`, {
                "is-required": required,
              })}
            >
              {typeof label !== "undefined" && (
                <label
                  htmlFor={htmlFor}
                  style={
                    fixedLabelWidth ? { width: fixedLabelWidth } : undefined
                  }
                >
                  {label}
                  {tips && (
                    <>
                      {" "}
                      <Bubble content={tips}>
                        <Icon type="info" />
                      </Bubble>
                    </>
                  )}
                </label>
              )}
            </div>
          )}
          <FormControl
            status={status}
            showStatusIcon={showStatusIcon}
            message={message}
            extra={extra}
            alignLabelTop={isAlignLabelTop(align, children)}
          >
            {children}
            {suffix && (
              <div className={`${classPrefix}-form__help-text--inline`}>
                {suffix}
              </div>
            )}
          </FormControl>
        </div>
      )}
    </FormContext.Consumer>
  );
});

FormItem.displayName = "FormItem";

function isAlignLabelTop(
  align: "auto" | "top" | "middle",
  children: React.ReactNode
): boolean {
  if (align === "top") {
    return true;
  }
  if (align === "middle") {
    return false;
  }
  return getDefaultAlign(children) === "top";
}

function getDefaultAlign(control: React.ReactNode) {
  if (
    React.isValidElement(control) &&
    // 普通组件是 function, forwaredRef 是 object
    (typeof control.type === "function" || typeof control.type === "object") &&
    "defaultLabelAlign" in control.type
  ) {
    return control.type["defaultLabelAlign"]; // eslint-disable-line dot-notation
  }
  return "top";
}
