import {addGoods, editGoods, getAllDepartment, getAllStorage, getGoodsInfo} from '@apis';
import {yupResolver} from '@hookform/resolvers/yup';
import {AddGoodsParams} from '@models';
import {useMutation, useQuery} from '@tanstack/react-query';
import {message} from 'antd';
import {useEffect} from 'react';
import {useForm, useFormContext} from 'react-hook-form';
import {number, object, string} from 'yup';

type FormState = {
  /** 品号 */
  goodsItemNumber: string;
  /** 品名 */
  goodsName: string;
  /** 类型 */
  goodsType: string;
  /** 库位容纳 */
  goodsMinAccommodate: number;
  /** 收容数 */
  goodsAccommodateNum: number;
  /** 最大容纳 */
  goodsMaxAccommodate: number;
  /** 供应商 */
  goodsSupplier: string;
  /** 库位 */
  goodsStorageLocation: string;
  /** 投入方式 */
  goodsInputType: string;
  /** 适用部门 */
  goodsUserDepartment: string;
  /** 低储量 */
  goodsLowReserves: number;
  /** 高储量 */
  goodsHighReserves: number;
  /** 等级 */
  goodsGrade: string;
  /** 包装类型 */
  goosdPackingType: string;
  /** 单位 */
  goodsUnit: string;

};

const validate = object({
  goodsItemNumber: string().required('请输入品号'),
  goodsType: string().required('请输入类型'),
  goodsMinAccommodate: number().typeError('请输入数字').required('请输入库位最小容纳')
    .min(0, '库位最小容纳不能小于0'),

  goodsMaxAccommodate: number().typeError('请输入数字').required('请输入库位最大容纳')
    .min(0, '库位最大容纳不能小于0'),

  goodsAccommodateNum: number().typeError('请输入数字').required('请输入收容数')
    .min(0, '收容数不能小于0'),

  goodsSupplier: string().required('请输入供应商'),
  goodsStorageLocation: string().required('请选择库位'),
  goodsInputType: string().required('请输入类型'),
  goodsUserDepartment: string().required('请选择适用部门'),
  goodsLowReserves: number().typeError('请输入数字').required('请输入低储量')
    .min(0, '低储量不能小于0'),

  goodsHighReserves: number().typeError('请输入数字').required('请输入高储量')
    .min(0, '高储量不能小于0'),

  goodsGrade: string().required('请输入等级'),
  goosdPackingType: string().required('请输入包装类型'),
  goodsUnit: string().required('请输入单位'),
  goodsName: string().required('请输入品名'),
});

function useAdd(onClose: () => void, onFetch: () => void) {
  const {isLoading, mutate} = useMutation(
    addGoods,
    {
      onSuccess({msg}) {
        if (msg === '200') {
          onClose();
          onFetch();
          message.success('新增成功');
        }
      },
    },
  );

  return [isLoading, mutate] as const;
}

function useEdit(onClose: () => void, onFetch: () => void) {
  const {isLoading, mutate} = useMutation(
    editGoods,
    {
      onSuccess({msg}) {
        if (msg === '200') {
          onClose();
          onFetch();
          message.success('修改成功');
        }
      },
    },
  );

  return [isLoading, mutate] as const;
}

export function useFormState(
  {id, visible, onClose, onFetch}:
  {id: string, visible: boolean, onClose: () => void, onFetch: () => void},
) {
  const formInstance = useForm<FormState>({
    resolver: yupResolver(validate),
    defaultValues: {
      goodsItemNumber: '',
      goodsType: '',
      goodsMinAccommodate: 0,
      goodsMaxAccommodate: 0,
      goodsAccommodateNum: 0,
      goodsSupplier: '',
      goodsStorageLocation: '',
      goodsInputType: '',
      goodsUserDepartment: '',
      goodsLowReserves: 0,
      goodsHighReserves: 0,
      goodsGrade: '',
      goosdPackingType: '',
      goodsUnit: '',
      goodsName: '',
    },
  });

  const {handleSubmit, clearErrors} = formInstance;

  useEffect(function() {
    visible && clearErrors();
  }, [clearErrors, visible]);

  const [isAddLoading, addMutate] = useAdd(onClose, onFetch);
  const [isEditLoading, editMutate] = useEdit(onClose, onFetch);
  const isLoading = isAddLoading || isEditLoading;

  const onSubmit = handleSubmit(function({
    goodsItemNumber,
    goodsType,
    goodsMinAccommodate,
    goodsAccommodateNum,
    goodsMaxAccommodate,
    goodsSupplier,
    goodsStorageLocation,
    goodsInputType,
    goodsUserDepartment,
    goodsLowReserves,
    goodsHighReserves,
    goodsGrade,
    goosdPackingType,
    goodsUnit,
    goodsName,
  }) {
    const params: AddGoodsParams = {
      name: goodsName,
      itemNumber: goodsItemNumber,
      type: goodsType,
      minAccommodate: String(goodsMinAccommodate),
      accommodateNum: String(goodsAccommodateNum),
      maxAccommodate: String(goodsMaxAccommodate),
      supplier: goodsSupplier,
      storageLocation: goodsStorageLocation,
      inputType: goodsInputType,
      userDepartment: goodsUserDepartment,
      lowReserves: String(goodsLowReserves),
      highReserves: String(goodsHighReserves),
      grade: goodsGrade,
      packingType: goosdPackingType,
      unit: goodsUnit,
    };

    id
      ? editMutate({...params, id})
      : addMutate(params);
  });

  return [{formInstance, isLoading}, {onSubmit}] as const;
}

export function useField() {
  const {control} = useFormContext<FormState>();

  return [{control}] as const;
}

export function useOptions() {
  const {data: departmentOptions} = useQuery(
    [getAllDepartment.name],
    async function() {
      const data = await getAllDepartment();

      if (data.msg === '200')
        return data.data.map(function({id, departmentName}) {
          return {
            value: String(id),
            label: departmentName,
          };
        });

      return [];
    },
    {initialData: []},
  );

  const {data: storageOptions} = useQuery(
    [getAllStorage.name],
    async function() {
      const data = await getAllStorage();

      if (data.msg === '200')
        return data.data.map(function({id, storageLocationName}) {
          return {
            value: String(id),
            label: storageLocationName,
          };
        });

      return [];
    },
    {initialData: []},
  );

  return {departmentOptions, storageOptions};
}

export function useFormValues(id: string) {
  const {setValue} = useFormContext<FormState>();

  const {data} = useQuery(
    [getGoodsInfo.name, id],
    async function() {
      const data = await getGoodsInfo(id);

      if (data.msg === '200') {
        if (data.data.list.length) return data.data.list[0];

        throw new Error('未获取到货品信息');
      }

      throw new Error(data.errMsg);
    },
    {enabled: Boolean(id), suspense: true, cacheTime: 0},
  );

  useEffect(function() {
    setValue('goodsName', data?.name ?? '');
    setValue('goodsItemNumber', data?.itemNumber ?? '');
    setValue('goodsType', data?.type ?? '');
    setValue('goodsAccommodateNum', Number(data?.accommodateNum ?? '0'));
    setValue('goodsMinAccommodate', Number(data?.minAccommodate ?? '0'));
    setValue('goodsMaxAccommodate', Number(data?.maxAccommodate ?? '0'));
    setValue('goodsSupplier', data?.supplier ?? '');
    setValue('goodsStorageLocation', data?.storageLocation ?? '');
    setValue('goodsInputType', data?.inputType ?? '');
    setValue('goodsUserDepartment', data?.userDepartment ?? '');
    setValue('goodsLowReserves', Number(data?.lowReserves ?? '0'));
    setValue('goodsHighReserves', Number(data?.highReserves ?? '0'));
    setValue('goodsGrade', data?.grade ?? '');
    setValue('goosdPackingType', data?.packingType ?? '');
    setValue('goodsUnit', data?.unit ?? '');
  }, [data, setValue]);
}
