import type { CSSProperties, VNode } from 'vue';
import {
  type AutoCompleteProps,
  type CalendarProps,
  type CascaderProps,
  type CheckboxGroupProps,
  type CheckboxProps,
  type DatePickerProps,
  type DynamicInputProps,
  type DynamicTagsProps,
  type FormItemRule,
  type GradientTextProps,
  type InputNumberProps,
  type InputProps,
  type MentionProps,
  type QrCodeProps,
  type RadioGroupProps,
  type RadioProps,
  type RateProps,
  type SelectProps,
  type SliderProps,
  type SwitchProps,
  type TimePickerProps,
  type TreeSelectProps,
  type UploadProps
} from 'naive-ui';
import {
  NAutoComplete,
  NCalendar,
  NCascader,
  NCheckbox,
  NCheckboxGroup,
  NDatePicker,
  NDynamicInput,
  NDynamicTags,
  NGradientText,
  NInput,
  NInputNumber,
  NMention,
  NQrCode,
  NRadio,
  NRadioGroup,
  NRate,
  NSelect,
  NSlider,
  NSwitch,
  NTimePicker,
  NTreeSelect,
  NUpload
} from 'naive-ui';
import type { GridItemProps, GridProps } from 'naive-ui/lib/grid';
import type { ButtonProps } from 'naive-ui/lib/button';
import { zUpload } from '@/components/zt/upload';
import dictSelect from '@/components/zt/dict-select/index.vue';
import { ApiSelect } from '../../ApiSelect';
import type { ApiSelectProps } from '../../ApiSelect/type';
import type { ApiTreeSelectProps } from '../../ApiTreeSelect/type';
import { ApiTreeSelect } from '../../ApiTreeSelect';
import type { zuploadProps } from '../../upload';
import type { disctSelectProps } from '../../dict-select';
// componentMap.ts
export interface FormProps {
  model?: Recordable;
  labelWidth?: number | string;
  schemas?: FormSchema[];
  inline?: boolean;
  layout?: string;
  size?: string;
  labelPlacement?: string;
  isFull?: boolean;
  showActionButtonGroup?: boolean;
  showResetButton?: boolean;
  resetButtonOptions?: Partial<ButtonProps>;
  showSubmitButton?: boolean;
  showAdvancedButton?: boolean;
  submitButtonOptions?: Partial<ButtonProps>;
  submitButtonText?: string;
  resetButtonText?: string;
  gridProps?: GridProps;
  giProps?: GridItemProps;
  resetFunc?: () => Promise<void>;
  submitFunc?: () => Promise<void>;
  submitOnReset?: boolean;
  baseGridStyle?: CSSProperties;
  collapsedRows?: number;
}

export interface FormActionType {
  submit: () => Promise<any>;
  setFormProps: (formProps: Partial<FormProps>) => Promise<void>;
  setSchema: (schemaProps: Partial<FormSchema[]>) => Promise<void>;
  setFieldsValue: (values: Recordable) => Promise<void>;
  clearValidate: (name?: string | string[]) => Promise<void>;
  getFieldsValue: () => Recordable;
  resetFields: () => Promise<void>;
  validate: (nameList?: any[]) => Promise<any>;
  setLoading: (status: boolean) => void;
  restoreValidation: () => void;
  updateSchema: (FormSchema: Partial<FormSchema> | Partial<FormSchema>[]) => void;
}

export type RegisterFn = (formInstance: FormActionType) => void;

export type UseFormReturnType = [RegisterFn, FormActionType];

interface NCheckboxGroupProps extends CheckboxGroupProps {
  options: { label: string; value: string | number }[];
}
interface NRadioGroupProps extends RadioGroupProps {
  options: { label: string; value: string | number }[];
}

export type FormSchema =
  | FormSchemaWithType<'NInput', InputProps>
  | FormSchemaWithType<'NInputNumber', InputNumberProps>
  | FormSchemaWithType<'NSelect', SelectProps>
  | FormSchemaWithType<'NDatePicker', DatePickerProps>
  | FormSchemaWithType<'NTimePicker', TimePickerProps>
  | FormSchemaWithType<'NSwitch', SwitchProps>
  | FormSchemaWithType<'NCheckboxGroup', NCheckboxGroupProps>
  | FormSchemaWithType<'NCheckbox', CheckboxProps>
  | FormSchemaWithType<'NRadioGroup', NRadioGroupProps>
  | FormSchemaWithType<'NRadio', RadioProps>
  | FormSchemaWithType<'NSlider', SliderProps>
  | FormSchemaWithType<'NRate', RateProps>
  | FormSchemaWithType<'NUpload', UploadProps>
  | FormSchemaWithType<'NCascader', CascaderProps>
  | FormSchemaWithType<'NTreeSelect', TreeSelectProps>
  | FormSchemaWithType<'NAutoComplete', AutoCompleteProps>
  | FormSchemaWithType<'NMention', MentionProps>
  | FormSchemaWithType<'NQrCode', QrCodeProps>
  | FormSchemaWithType<'NCalendar', CalendarProps>
  | FormSchemaWithType<'NDynamicTags', DynamicTagsProps>
  | FormSchemaWithType<'ApiSelect', ApiSelectProps>
  | FormSchemaWithType<'ApiTreeSelect', ApiTreeSelectProps>
  | FormSchemaWithType<'zUpload', zuploadProps>
  | FormSchemaWithType<'NDynamicInput', DynamicInputProps>
  | FormSchemaWithType<'NGradientText', GradientTextProps>
  | FormSchemaWithType<'dictSelect', disctSelectProps>;

export interface RenderCallbackParams {
  schema: FormSchema;
  values: Recordable;
  model: Recordable;
  field: string;
}
interface FormSchemaWithType<T extends keyof ComponentMap, P> {
  /**
   * 字段名
   */
  field: string;
  /**
   * 标题
   */
  label?: string;
  /**
   * 组件类型
   */
  component: T;
  /**
   * 组件属性Props
   */
  componentProps?: P;
  /**
   * 是否必填
   */
  required?: boolean;
  /**
   * 组件校验规则
   */
  rules?: FormItemRule | FormItemRule[]; // 校验规则
  /**
   * 默认值
   */
  defaultValue?: any; // 默认值
  /**
   * 是否显示
   */
  show?: boolean;
  labelMessage?: string;
  labelMessageStyle?: object | string;
  giProps?: GridItemProps;
  isFull?: boolean;
  suffix?: string;
  slot?: string;
  /**
   * 是否显示，渲染函数
   */
  ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
  /**
   * 自定义渲染
   * @param renderCallbackParams
   * @returns
   */
  render?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string;
}

export const componentMap = {
  NInput,
  NInputNumber,
  NSelect,
  NDatePicker,
  NTimePicker,
  NSwitch,
  NCheckboxGroup,
  NCheckbox,
  NRadioGroup,
  NRadio,
  NSlider,
  NRate,
  NUpload,
  NCascader,
  NTreeSelect,
  NAutoComplete,
  NQrCode,
  NCalendar,
  NDynamicTags,
  NMention,
  ApiSelect,
  ApiTreeSelect,
  zUpload,
  NDynamicInput,
  NGradientText,
  dictSelect
} as const;

export type ComponentMap = typeof componentMap;
