import { toCamelCase } from '@/tools';
import { regionsMethod } from '@/request/api';

import type { FieldRule, NumberKeyboardProps, PasswordInputProps } from 'vant';

export type Option = { label: string; value: string; checked?: boolean;  disabled?: boolean; editable?: boolean; single?: boolean; }
export type Dictionaries = Map<string, Option[]>;

export type CascaderOption = { label: string; value: string; children?: CascaderOption[] };

export interface RegisterModel {
  cardno: string;
  phone: string;
  code: string;
  name: string;
  sex: string;
  age: number;
  height: number;
  weight: number;
  isEasyAllergy: boolean;
  womenSpecialPeriod: string;
  foodAllergy: string;
  hobbyFlavor: string;
  drinkState: boolean;
  smokeState: boolean;
  address: { label: string; value: string }[];
  detailAddress: string;
  job: string;
}

export interface Field {
  name?: FieldKey;
  control: {
    label: string; placeholder?: string;
    type?: string; min?: number; max?: number; minlength?: number; maxlength?: number;
    clearable?: boolean; border?: boolean; readonly?: boolean;
    hide?: boolean | ((model: Record<string, any>) => boolean);
  };
  component?:
    | { name: 'picker'; options: Option[]; props?: Partial<{ multiple: boolean; immediate?: boolean }> }
    | { name: 'radio'; options: Option[] }
    | { name: 'cascader'; options: CascaderOption[] | (() => CascaderOption[]) | (() => Promise<CascaderOption[]>) }
    | { name: 'code'; props?: Partial<PasswordInputProps> };
  keyboard?: { show: boolean } & Partial<NumberKeyboardProps>;
  suffix?: string;
  rules: FieldRule[];
}

export type FieldKey = keyof RegisterModel;
export type Fields = Field[];

export const Field_Config: Record<FieldKey, Field> = {
  height: {
    control: {
      label: '身高', placeholder: '请输入身高',
      type: 'number', min: 1, max: 300, clearable: true, readonly: true,
      maxlength: 5,
    },
    keyboard: { show: false, title: '身高', extraKey: '.', closeButtonText: '完成' },
    suffix: 'cm',
    rules: [],
  },
  weight: {
    control: {
      label: '体重', placeholder: '请输入体重',
      type: 'number', min: 1, max: 300, clearable: true, readonly: true,
      maxlength: 5,
    },
    keyboard: { show: false, title: '体重', extraKey: '.', closeButtonText: '完成' },
    suffix: 'kg',
    rules: [],
  },
  age: {
    control: {
      label: '年龄', placeholder: '请输入年龄',
      type: 'digit', min: 0, max: 300, clearable: true, readonly: true,
      maxlength: 3,
    },
    keyboard: { show: false, title: '年龄', closeButtonText: '完成' },
    suffix: '岁',
    rules: [],
  },
  sex: {
    control: { label: '性别', border: false },
    component: {
      name: 'radio' as const,
      options: 'sys_user_sex' as unknown as any,
    },
    rules: [],
  },
  womenSpecialPeriod: {
    control: {
      label: '女性特殊期', readonly: true,
      hide(model) { return model?.sex !== '1'; },
    },
    component: {
      name: 'picker' as const,
      options: 'women_special_period' as unknown as any,
      props: { multiple: false },
    },
    rules: [],
  },
  foodAllergy: {
    control: { label: '食物过敏', readonly: true },
    component: {
      name: 'picker' as const,
      options: 'food_allergy' as unknown as any,
      props: { multiple: true },
    },
    rules: [],
  },
  hobbyFlavor: {
    control: { label: '喜好口味', readonly: true },
    component: {
      name: 'picker' as const,
      options: 'hobby_flavor' as unknown as any,
      props: { multiple: true },
    },
    rules: [],
  },
  job: {
    control: { label: '职业', readonly: true },
    component: {
      name: 'picker' as const,
      options: 'job' as unknown as any,
      props: { multiple: false, immediate: true },
    },
    rules: [],
  },
  isEasyAllergy: {
    control: { label: '容易过敏', border: false },
    component: {
      name: 'radio' as const,
      options: 'sys_yes_no' as unknown as any,
    },
    rules: [],
  },
  drinkState: {
    control: { label: '饮酒情况', border: false },
    component: {
      name: 'radio' as const,
      options: 'sys_yes_no' as unknown as any,
    },
    rules: [],
  },
  smokeState: {
    control: { label: '吸烟情况', border: false },
    component: {
      name: 'radio' as const,
      options: 'sys_yes_no' as unknown as any,
    },
    rules: [],
  },
  address: {
    control: { label: '现住址', readonly: true },
    component: {
      name: 'cascader' as const,
      options: () => regionsMethod().send(),
    },
    rules: [],
  },
  detailAddress: {
    control: {
      label: '详细地址', placeholder: '请输入详细地址',
      type: 'text', maxlength: 100, clearable: true,
    },
    rules: [],
  },
  name: {
    control: {
      label: '姓名', placeholder: '请输入姓名',
      type: 'text', maxlength: 10, clearable: true,
    },
    rules: [],
  },
  cardno: {
    control: {
      label: '身份证号', placeholder: '请输入身份证号',
      type: 'text', maxlength: 18, minlength: 18, clearable: true, readonly: true,
    },
    keyboard: { show: false, title: '身份证号', extraKey: 'X', closeButtonText: '完成' },
    rules: [
      {
        validator: (value: string) => value && value.length === 18,
        message: '请输入正确的身份证',
        trigger: 'onBlur',
      },
    ],
  },
  phone: {
    control: {
      label: '手机号码', placeholder: '请输入手机号码',
      type: 'tel', maxlength: 11, minlength: 11, clearable: true, readonly: true,
    },
    keyboard: { show: false, title: '手机号码', closeButtonText: '完成' },
    rules: [
      {
        validator: (value: string) => value && value.length === 11,
        message: '请输入正确的手机号码',
        trigger: 'onBlur',
      },
    ],
  },
  code: {
    control: {
      label: '验证码', placeholder: '请输入验证码',
      type: 'digit', maxlength: 6, minlength: 6, clearable: true,
      border: false,
    },
    component: {
      name: 'code' as const,
      props: { mask: false },
    },
    keyboard: { show: false, title: '验证码', closeButtonText: '完成' },
    rules: [
      {
        validator: (value: string) => value && value.length === 6,
        message: '请输入验证码',
        trigger: [ 'onChange', 'onBlur' ],
      },
    ],
  },
};

export function fromRegisterFields(options: string[], dictionaries?: Dictionaries): Fields {
  dictionaries ??= new Map([
    ['sys_yes_no', [{ label: '是', value: 'Y' }, { label: '否', value: 'N' }]],
    ['sys_user_sex', [{ label: '男', value: '0' }, { label: '女', value: '1' }]]
  ]);
  const getOptions = (options?: Option[] | string | Function): Option[] | Function => {
    if (typeof options === 'function') return options;
    if (options == null) options = [];
    if (typeof options === 'string') options = dictionaries?.get(options) ?? [];
    return options.map((option) => Object.assign({
      editable: option.label === `其他`,
      single: option.label === `无`,
    } ,option));
  };

  // 修正 phone,code
  const k1 = 'phone';
  const k2 = 'code';
  const index = options.findIndex(key => key.startsWith(k1));
  if ( index !== -1 && !options.find(key => key.startsWith(k2)) ) {
    const value = options[ index ].replace(k1, k2);
    options.splice(index + 1, 0, value);
  }

  return options.map(option => {
    const values = option.split(':');
    const name = toCamelCase(values[ 0 ]);
    const field = Field_Config[ name as unknown as FieldKey ] ?? {
      control: { label: name, type: 'text' },
      rules: [],
    };
    if ((field.component as any)?.options) (field.component as any) = { ...field.component, options: getOptions((field.component as any).options) }
    if ( values[ 1 ] === 'required' ) field.rules.push({ required: true, message: field.control.placeholder ?? '请补充完整' });
    return { ...field, name } as Fields[number];
  });
}
