import { InfoCircleOutlined } from "@ant-design/icons";
import {
  Button,
  Checkbox,
  Col,
  DatePicker,
  Divider,
  Form,
  Input,
  InputNumber,
  Radio,
  Row,
  Select,
  Tooltip,
} from "antd";
import dayjs from "dayjs";
import { FORM_ITEM_RENDER_ENUM } from "../../enum/formItemRender";
import { getDataType } from "../../utils";

const { TextArea } = Input;
const { RangePicker } = DatePicker;

/**
 * 表单项渲染器组件
 * @param {object} props - 组件属性
 * @param {Array} props.options - 表单配置项数组
 * @param {object} props.labelCol - label 栅格配置
 * @param {number} props.gutter - 栅格间距
 * @param {number} props.span - 默认栅格占据列数
 * @param {boolean} props.collapse - 是否折叠（仅显示前3项）
 * @param {boolean} props.useAutoGenerateRequired - 是否自动生成必填规则
 * @param {object} props.initialValues - 初始值
 */
const FormItemsRenderer = ({
  options,
  labelCol,
  gutter = 24,
  span = 12,
  collapse = false,
  useAutoGenerateRequired = true,
  initialValues,
}) => {
  const form = Form.useFormInstance();

  // 获取表单值，优先使用 initialValues
  const getFormValues = () => {
    const formValues = form.getFieldsValue();
    // 如果表单值为空但有 initialValues，则使用 initialValues
    if (Object.keys(formValues).length === 0 && initialValues) {
      return initialValues;
    }
    return formValues;
  };

  // 获取传给组件的属性
  const getComponentProps = (option) => {
    return typeof option.componentProps === "function"
      ? option.componentProps(getFormValues())
      : (option.componentProps || {});
  };

  // 获取 Form.List 独有的属性
  const getFormListUniqueProps = (option) => {
    const defaultProps = {
      showAddButton: true,
      showRemoveButton: true,
      addButtonText: "添加",
      removeButtonText: "删除",
      options: [],
      addDefaultValue: {},
      addInsertIndex: undefined,
    };

    if (typeof option.formListUniqueProps === "function") {
      return {
        ...defaultProps,
        ...option.formListUniqueProps(getFormValues()),
      };
    }

    return {
      ...defaultProps,
      ...(option.formListUniqueProps || {}),
    };
  };

  // 设置日期组件的属性
  const setDateComponentProps = (option, formItemProps) => {
    // 为日期组件添加特殊处理
    if ([
      FORM_ITEM_RENDER_ENUM.DATE,
      FORM_ITEM_RENDER_ENUM.DATE_MONTH,
      FORM_ITEM_RENDER_ENUM.DATE_YEAR,
      FORM_ITEM_RENDER_ENUM.DATETIME,
    ].includes(option.render)) {
      formItemProps.getValueFromEvent = (_, dateString) => dateString;
      formItemProps.getValueProps = value => ({ value: value ? dayjs(value) : undefined });
    }

    // 为日期周组件添加特殊处理
    if ([
      FORM_ITEM_RENDER_ENUM.DATE_WEEK,
    ].includes(option.render)) {
      formItemProps.getValueFromEvent = (_, dateString) => dateString;
      formItemProps.getValueProps = value => ({ value: value ? dayjs(value, "YYYY-wo") : undefined });
    }

    // 为日期范围组件添加特殊处理
    if ([
      FORM_ITEM_RENDER_ENUM.DATE_RANGE,
      FORM_ITEM_RENDER_ENUM.DATETIME_RANGE,
    ].includes(option.render)) {
      formItemProps.getValueFromEvent = (_, dateString) => dateString;
      formItemProps.getValueProps = value => ({ value: Array.isArray(value) ? value.map(v => v ? dayjs(v) : undefined) : undefined });
    }
  };

  // 获取传给 formItem 的属性
  const getFormItemProps = (option) => {
    const formItemProps = typeof option.formItemProps === "function"
      ? option.formItemProps(getFormValues())
      : (option.formItemProps || {});

    setDateComponentProps(option, formItemProps);

    return formItemProps;
  };

  // 获取items里的value和label字段key
  const getItemsFieldKey = (option) => {
    return {
      valueKey: option?.itemsField?.valueKey || "bianma",
      labelKey: option?.itemsField?.labelKey || "name",
    };
  };

  // 获取 required
  const getRequired = (required) => {
    // 支持动态计算 required
    return typeof required === "function"
      ? required(getFormValues())
      : (required ?? true);
  };

  // 获取验证规则
  const getRules = (option) => {
    if (option.render === FORM_ITEM_RENDER_ENUM.DIVIDER)
      return [];

    const rules = [];

    /** @type {string | Function} */
    const render = option.render || FORM_ITEM_RENDER_ENUM.INPUT;
    switch (render) {
      case FORM_ITEM_RENDER_ENUM.INPUT:
        option.useConstraints !== false && rules.push({ max: 50, message: "最多输入50字符" });
        break;

      case FORM_ITEM_RENDER_ENUM.TEXTAREA:
        option.useConstraints !== false && rules.push({ max: 500, message: "最多输入500字符" });
        break;

      case FORM_ITEM_RENDER_ENUM.INPUT_NUMBER:
      case FORM_ITEM_RENDER_ENUM.NUMBER:
        option.useConstraints !== false && rules.push({ pattern: /^(\d+)(\.\d{1,2})?$/, message: "请输入正确的数字，最多保留两位小数" });
        option.useConstraints !== false && rules.push({
          validator: (_, value) => {
            if (value && Math.abs(Number.parseFloat(value)) > 999999999) {
              return Promise.reject("输入数值超出安全范围");
            }
            return Promise.resolve();
          },
        });
        break;

      case FORM_ITEM_RENDER_ENUM.INTEGER:
        option.useConstraints !== false && rules.push({ pattern: /^(\d+)$/, message: "请输入正确的整数" });
        option.useConstraints !== false && rules.push({
          validator: (_, value) => {
            if (value && Math.abs(Number.parseFloat(value)) > 999999999) {
              return Promise.reject("输入数值超出安全范围");
            }
            return Promise.resolve();
          },
        });
        break;
    }

    if (!useAutoGenerateRequired)
      return option.rules ? (Array.isArray(option.rules) ? [...option.rules, ...rules] : [option.rules, ...rules]) : rules;

    if (getRequired(option.required)) {
      const isBlurTrigger = !option.render || [
        FORM_ITEM_RENDER_ENUM.INPUT,
        FORM_ITEM_RENDER_ENUM.TEXTAREA,
        FORM_ITEM_RENDER_ENUM.INPUT_NUMBER,
        FORM_ITEM_RENDER_ENUM.NUMBER,
        FORM_ITEM_RENDER_ENUM.INTEGER,
      ].includes(option.render);

      rules.push({ required: true, message: `${isBlurTrigger ? "请输入" : "请选择"}${option.label}` });
    }

    return option.rules ? (Array.isArray(option.rules) ? [...option.rules, ...rules] : [option.rules, ...rules]) : rules;
  };

  // 获取key
  const getKey = (option) => {
    return option.key || (getDataType(option.name) === "Array" ? option.name.join(".") : option.name);
  };

  // 使用 style 控制显示/隐藏
  const getStyle = (index) => {
    return collapse && index >= 3 ? { display: "none" } : undefined;
  };

  // 列数
  const getCol = (option) => {
    const itemSpan = option.render === FORM_ITEM_RENDER_ENUM.DIVIDER ? 24 : (option.span ?? span);
    // 这里除以2是因为：一行两列的span为4，一行一列的span要为2，不除以2的话一行一列的span不对
    const itemLabelCol = option.labelCol ?? (itemSpan === 24 ? { span: labelCol.span / 2 } : labelCol);
    const itemWrapperCol = option.wrapperCol ?? { span: 24 - itemLabelCol.span };
    return { span: itemSpan, labelCol: itemLabelCol, wrapperCol: itemWrapperCol };
  };

  // 获取 col 样式
  const getColStyle = (option) => {
    return typeof option.colStyle === "function"
      ? option.colStyle(getFormValues())
      : option.colStyle;
  };

  // 获取 col 标题（Col 内部、Form.Item 之后）
  const getColTitle = (option) => {
    return typeof option.colTitle === "function"
      ? option.colTitle(getFormValues())
      : option.colTitle;
  };

  // 获取 row 样式（FormList 的每一行）
  const getRowStyle = (option, field, fieldIndex) => {
    return typeof option.rowStyle === "function"
      ? option.rowStyle(field, fieldIndex)
      : option.rowStyle;
  };

  // 获取 row 标题（FormList 每行末尾）
  const getRowTitle = (option, field, fieldIndex) => {
    return typeof option.rowTitle === "function"
      ? option.rowTitle(field, fieldIndex)
      : option.rowTitle;
  };

  // 获取是否动态表单项
  const getIsDynamicFormItem = (option, formItemProps) => {
    return (option.shouldUpdate ?? option.dependencies) || (formItemProps.shouldUpdate ?? formItemProps.dependencies);
  };

  // 获取 hidden
  const getHidden = (hidden) => {
    // 支持动态计算 hidden
    return typeof hidden === "function"
      ? hidden(getFormValues())
      : (hidden ?? false);
  };

  // 获取 listOptions
  const getListOptions = (listOptions, field, fieldIndex, add, remove, move) => {
    return typeof listOptions === "function"
      ? listOptions(field, fieldIndex, { field, fieldIndex, add, remove, move })
      : (listOptions ?? []);
  };

  // 获取可选项的属性（适用于 SELECT、RADIO、CHECKBOX）
  const getSelectableItemAttributes = (item, itemsFieldKey) => {
    const value = item[itemsFieldKey.valueKey];
    const label = typeof itemsFieldKey.labelKey === "function" ? itemsFieldKey.labelKey(item) : item[itemsFieldKey.labelKey];
    const disabled = item.disabled;

    return { value, label, disabled };
  };

  // 渲染表单控件
  const renderFormControl = (option) => {
    const componentProps = getComponentProps(option);
    const itemsFieldKey = getItemsFieldKey(option);
    /** @type {string | Function} */
    const render = option.render ?? FORM_ITEM_RENDER_ENUM.INPUT;
    const placeholder = option.placeholder ?? `请${[FORM_ITEM_RENDER_ENUM.INPUT, FORM_ITEM_RENDER_ENUM.TEXTAREA, FORM_ITEM_RENDER_ENUM.INPUT_NUMBER, FORM_ITEM_RENDER_ENUM.NUMBER, FORM_ITEM_RENDER_ENUM.INTEGER].includes(render) ? "输入" : "选择"}${option.label}`;

    switch (render) {
      case FORM_ITEM_RENDER_ENUM.INPUT:
        return <Input placeholder={placeholder} maxLength={option.useConstraints !== false ? 50 : 9999} {...componentProps} />;

      case FORM_ITEM_RENDER_ENUM.TEXTAREA:
        return <TextArea placeholder={placeholder} maxLength={option.useConstraints !== false ? 500 : 9999} showCount={true} rows={3} {...componentProps} />;

      case FORM_ITEM_RENDER_ENUM.INPUT_NUMBER:
      case FORM_ITEM_RENDER_ENUM.NUMBER:
      case FORM_ITEM_RENDER_ENUM.INTEGER:
        return <InputNumber placeholder={placeholder} style={{ width: "100%" }} {...componentProps} />;

      case FORM_ITEM_RENDER_ENUM.SELECT:
        return (
          <Select placeholder={placeholder} showSearch={{ optionFilterProp: "children" }} allowClear {...componentProps}>
            {(option.items || []).map((item) => {
              const { value, label, disabled } = getSelectableItemAttributes(item, itemsFieldKey);
              return (
                <Select.Option key={value} value={value} disabled={disabled}>
                  {label}
                </Select.Option>
              );
            })}
          </Select>
        );

      case FORM_ITEM_RENDER_ENUM.RADIO:
        return (
          <Radio.Group {...componentProps}>
            {(option.items || []).map((item) => {
              const { value, label, disabled } = getSelectableItemAttributes(item, itemsFieldKey);
              return (
                <Radio key={value} value={value} disabled={disabled}>
                  {label}
                </Radio>
              );
            })}
          </Radio.Group>
        );

      case FORM_ITEM_RENDER_ENUM.CHECKBOX:
        return (
          <Checkbox.Group {...componentProps}>
            {
              option.checkboxCol
                ? (
                    <Row>
                      {(option.items || []).map((item) => {
                        const { value, label, disabled } = getSelectableItemAttributes(item, itemsFieldKey);
                        return (
                          <Col span={option.checkboxCol} key={value}>
                            <Checkbox value={value} disabled={disabled}>
                              {label}
                            </Checkbox>
                          </Col>
                        );
                      })}
                    </Row>
                  )
                : (
                    (option.items || []).map((item) => {
                      const { value, label, disabled } = getSelectableItemAttributes(item, itemsFieldKey);
                      return (
                        <Checkbox key={value} value={value} disabled={disabled}>
                          {label}
                        </Checkbox>
                      );
                    })
                  )
            }
          </Checkbox.Group>
        );

      case FORM_ITEM_RENDER_ENUM.DATE:
        return <DatePicker placeholder={placeholder} format="YYYY-MM-DD" style={{ width: "100%" }} {...componentProps} />;

      case FORM_ITEM_RENDER_ENUM.DATE_MONTH:
        return (
          <DatePicker
            picker="month"
            placeholder={placeholder}
            format="YYYY-MM"
            style={{ width: "100%" }}
            {...componentProps}
          />
        );

      case FORM_ITEM_RENDER_ENUM.DATE_YEAR:
        return (
          <DatePicker
            picker="year"
            placeholder={placeholder}
            format="YYYY"
            style={{ width: "100%" }}
            {...componentProps}
          />
        );

      case FORM_ITEM_RENDER_ENUM.DATE_WEEK:
        return (
          <DatePicker
            picker="week"
            placeholder={placeholder}
            format="YYYY-wo"
            style={{ width: "100%" }}
            {...componentProps}
          />
        );

      case FORM_ITEM_RENDER_ENUM.DATE_RANGE:
        return (
          <RangePicker
            placeholder={[`请选择开始${option.label}`, `请选择结束${option.label}`]}
            format="YYYY-MM-DD"
            style={{ width: "100%" }}
            {...componentProps}
          />
        );

      case FORM_ITEM_RENDER_ENUM.DATETIME:
        return (
          <DatePicker
            showTime
            placeholder={placeholder}
            format="YYYY-MM-DD HH:mm:ss"
            style={{ width: "100%" }}
            {...componentProps}
          />
        );

      case FORM_ITEM_RENDER_ENUM.DATETIME_RANGE:
        return (
          <RangePicker
            showTime
            placeholder={[`请选择开始${option.label}`, `请选择结束${option.label}`]}
            format="YYYY-MM-DD HH:mm:ss"
            style={{ width: "100%" }}
            {...componentProps}
          />
        );

      case FORM_ITEM_RENDER_ENUM.DIVIDER:
        return null;

      default:
        return render;
    }
  };

  // 渲染 label（带提示）
  const renderLabel = (option) => {
    if (!option.tip)
      return option.label;

    return (
      <>
        {option.label}
        <Tooltip title={option.tip}>
          <InfoCircleOutlined style={{ marginLeft: 4, fontSize: 12 }} />
        </Tooltip>
      </>
    );
  };

  // 渲染普通表单项
  const renderFormItem = ({ option, style, col, index, preserve }) => {
    const formItemProps = getFormItemProps(option);
    delete formItemProps.dependencies;
    delete formItemProps.shouldUpdate;

    if (getHidden(option.hidden))
      return null;

    return (
      <Col key={getKey(option) || index} span={col.span} style={{ ...style, ...getColStyle(option) }}>
        {getColTitle(option)}
        <Form.Item
          name={option.name}
          label={renderLabel(option)}
          rules={getRules(option)}
          labelCol={col.labelCol}
          wrapperCol={col.wrapperCol}
          preserve={preserve}
          required={useAutoGenerateRequired ? (renderLabel(option) === " " ? false : getRequired(option.required)) : false}
          colon={renderLabel(option) !== " "}
          {...formItemProps}
        >
          {renderFormControl(option)}
        </Form.Item>
      </Col>
    );
  };

  // 渲染特殊类型的表单项
  const renderOtherTypeItem = ({ option, style, col, index, preserve }) => {
    const componentProps = getComponentProps(option);

    // 如果是 customizeRender 类型，完全交给外部控制渲染
    if (option.customizeRender) {
      return (
        <Col key={getKey(option) || index} span={col.span} style={style}>
          {option.render}
        </Col>
      );
    }

    // 如果是 onlyForLabel 类型，不渲染任何UI，只在表单中保存数据
    if (option.onlyForLabel) {
      return (
        <Form.Item
          key={getKey(option) || index}
          name={option.name}
          noStyle
          preserve={preserve}
        >
          <input type="hidden" />
        </Form.Item>
      );
    }

    // 如果是分割线
    if (option.render === FORM_ITEM_RENDER_ENUM.DIVIDER) {
      return (
        <Col key={getKey(option) || index} span={col.span} style={style}>
          <Divider orientation="left" {...componentProps}>{option.label}</Divider>
        </Col>
      );
    }

    return null;
  };

  // 渲染需要动态更新的表单项
  const renderDynamicFormItem = ({ option, index, style, col, preserve }) => {
    const formItemProps = getFormItemProps(option);

    return (
      <Form.Item
        key={getKey(option) || index}
        noStyle
        preserve={preserve}
        shouldUpdate={option.shouldUpdate ?? formItemProps.shouldUpdate}
        dependencies={option.dependencies ?? formItemProps.dependencies}
      >
        {() => {
          return renderFormItem({ option, style, col, index, preserve });
        }}
      </Form.Item>
    );
  };

  // 渲染 Form.List
  const renderFormList = ({ option, index, col, style }) => {
    const formListUniqueProps = getFormListUniqueProps(option);
    const componentProps = getComponentProps(option);

    return (
      <Col key={getKey(option) || index} span={col.span} style={{ ...style, ...getColStyle(option) }}>
        {getColTitle(option)}
        <Form.List name={option.name} {...componentProps}>
          {(fields, { add, remove, move }) => (
            <>
              {fields.map((field, fieldIndex) => {
                const listOptions = getListOptions(formListUniqueProps.options, field, fieldIndex, add, remove, move);
                const rowStyle = getRowStyle(option, field, fieldIndex);
                const rowTitle = getRowTitle(option, field, fieldIndex);
                return (
                  <Row gutter={gutter} key={field.key} style={rowStyle}>
                    {rowTitle}
                    {listOptions.map((listOption, listIndex) => {
                      const col = getCol(listOption);
                      const formItemProps = getFormItemProps(listOption);

                      const params = {
                        option: listOption,
                        style,
                        col,
                        index: `${fieldIndex}_${listIndex}`,
                        preserve: true,
                      };
                      const otherTypeItem = renderOtherTypeItem(params);
                      if (otherTypeItem)
                        return otherTypeItem;

                      if (listOption.render === FORM_ITEM_RENDER_ENUM.FORM_LIST)
                        return renderFormList(params);

                      if (getIsDynamicFormItem(listOption, formItemProps))
                        return renderDynamicFormItem(params);

                      // 判断一个项是否需要显示按钮（不是 onlyForLabel 且不是隐藏的）
                      const isShow = (opt) => {
                        return !getHidden(opt.hidden) && !opt.onlyForLabel;
                      };

                      // 从后往前找，找到第一个需要显示按钮的项的索引
                      const findLastShowIndex = () => {
                        for (let i = listOptions.length - 1; i >= 0; i--) {
                          const opt = listOptions[i];
                          if (opt.render === FORM_ITEM_RENDER_ENUM.FORM_LIST)
                            return i;
                          if (isShow(opt))
                            return i;
                        }
                        return -1;
                      };

                      // 判断下一个是否是嵌套的 FormList，或者是 onlyForLabel/hidden 项
                      const nextOption = listOptions[listIndex + 1];
                      const isNextNestedFormList = nextOption && nextOption.render === FORM_ITEM_RENDER_ENUM.FORM_LIST;
                      const isNextNoShow = nextOption && !isShow(nextOption);

                      // 如果是最后一个需要显示按钮的项，或者下一个是嵌套的 FormList，或者下一个不需要按钮，则在其后添加操作按钮
                      const lastShowIndex = findLastShowIndex();
                      if (listIndex === lastShowIndex || isNextNestedFormList || isNextNoShow) {
                        delete formItemProps.dependencies;
                        delete formItemProps.shouldUpdate;

                        return (
                          <Col key={getKey(listOption) || listIndex} span={col.span} style={{ ...style, ...getColStyle(listOption) }}>
                            {getColTitle(listOption)}
                            <Form.Item
                              label={renderLabel(listOption)}
                              labelCol={col.labelCol}
                              wrapperCol={col.wrapperCol}
                              preserve={false}
                              required={useAutoGenerateRequired ? (renderLabel(listOption) === " " ? false : getRequired(listOption.required)) : false}
                              colon={renderLabel(listOption) !== " "}
                              {...formItemProps}
                            >
                              <div style={{ display: "flex", gap: 10, alignItems: "center", justifyContent: "space-between" }}>
                                <div style={{ flex: 1, minWidth: 0 }}>
                                  <Form.Item
                                    noStyle
                                    rules={getRules(listOption)}
                                    name={listOption.name}
                                  >
                                    {renderFormControl(listOption)}
                                  </Form.Item>
                                </div>
                                {
                                  // 只有当不是第一行时才显示删除按钮
                                  fieldIndex >= 1
                                    ? (
                                        formListUniqueProps.showRemoveButton
                                        && (
                                          <Button
                                            type="primary"
                                            danger
                                            onClick={() => remove(field.name)}
                                          >
                                            {formListUniqueProps.removeButtonText}
                                          </Button>
                                        )
                                      )
                                    : (
                                      // 第一行显示添加按钮
                                        formListUniqueProps.showAddButton
                                        && (
                                          <Button
                                            type="primary"
                                            onClick={() => add(formListUniqueProps.addDefaultValue, formListUniqueProps.addInsertIndex)}
                                          >
                                            {formListUniqueProps.addButtonText}
                                          </Button>
                                        )
                                      )
                                }
                              </div>
                            </Form.Item>
                          </Col>
                        );
                      }

                      return renderFormItem(params);
                    })}
                  </Row>
                );
              })}
            </>
          )}
        </Form.List>
      </Col>
    );
  };

  return (
    <>
      {options.map((option, index) => {
        const col = getCol(option);
        const style = getStyle(index);
        const formItemProps = getFormItemProps(option);

        const params = {
          option,
          style,
          col,
          index,
          preserve: false,
        };

        // 处理特殊类型的表单项
        const otherTypeItem = renderOtherTypeItem(params);
        if (otherTypeItem)
          return otherTypeItem;

        // 如果是 Form.List
        if (option.render === FORM_ITEM_RENDER_ENUM.FORM_LIST)
          return renderFormList(params);

        // 如果配置了 shouldUpdate 或 dependencies，使用 Form.Item 的联动机制
        if (getIsDynamicFormItem(option, formItemProps))
          return renderDynamicFormItem(params);

        // 普通表单项（静态配置）
        return renderFormItem(params);
      })}
    </>
  );
};

FormItemsRenderer.displayName = "FormItemsRenderer";

export default FormItemsRenderer;
