<template>
  <view class="form com-form">

    <div class="form-content">
      <wd-form v-if="items.length > 0" ref="formRef" :model="formState" :rules="formRules">
        <wd-cell-group border v-for="(item, inx) in items" :key="item.name"
          >
          <div class="form-item">
            <wd-input
              v-if="!item.type"
              :label="item.hideLabel ? '' : item.label"
              :prop="item.name"
              v-model="formState[item.name]"
              :placeholder="item.placeholder || `请输入${item.label}`" />
            <wd-input
              v-else-if="item.type === 'input'"
              :type="(item.inputType as any)"
              :bindnicknamereview="item.bindnicknamereview"
              :label="item.hideLabel ? '' : item.label"
              :prop="item.name"
              :placeholder="item.placeholder || `请输入${item.label}`"
              v-model="formState[item.name]" />
            <wd-textarea
              v-else-if="item.type === 'textarea'"
              :label="item.hideLabel ? '' : item.label"
              :prop="item.name"
              :placeholder="item.placeholder || `请输入${item.label}`"
              :maxlength="item.maxlength"
              show-word-limit
              v-model="formState[item.name]" />
            <wd-cell v-else-if="item.type === 'avatar'" class="avatar" :title="item.hideLabel ? '' : item.label" :prop="item.name">

              <image :src="formState[item.name] ? formState[item.name] : avatarImg"
                style="width: 44px; height: 44px; border-radius: 32px;" mode="aspectFill" />
              <wd-button custom-class="hide-bt" open-type="chooseAvatar"
                @chooseavatar="(ev: any) => item.onbindchooseavatar?.(ev)" />
            </wd-cell>
            <wd-cell v-else-if="item.type === 'image'" :title="item.hideLabel ? '' : item.label" :prop="item.name">
              <wd-upload
                v-model:file-list="formState[item.name]"
                action="https://ftf.jd.com/api/uploadImg"
                :multiple="item.multiple"
                :limit="item.limit"
                :upload-method="async(file: any, formData: any, options: any) => {
                  await handleUpload(item, file, formData, options);
                }"
                 />
            </wd-cell>
            <div v-else-if="item.type === 'qrcode'" class="qrcode">

              <image :src="avatarImg" style="width: 100%; " mode="widthFix" />

            </div>
            <div v-else-if="item.type === 'scan'" class="qrcode">

              <image :src="avatarImg" style="width: 100%; " mode="widthFix" @click="() => handleScan(item.handler)" />

            </div>

            <wd-picker
              v-else-if="item.type === 'time-pick'"
              :immediate-change="true"
              :columns="timePickerColumns"
              :label="item.hideLabel ? '' : item.label"
              :prop="item.name"
              v-model="formState[item.name]" />

            <wd-picker
              v-else-if="item.type === 'pick'"
              :immediate-change="true"
              :columns="item.options"
              :label="item.hideLabel ? '' : item.label"
              :prop="item.name"
              :display-format="item.displayFormat"
              :before-confirm="item.beforeConfirm"
              v-model="formState[item.name]" />


            <wd-cell v-else-if="item.type === 'radio'" :title="item.hideLabel ? '' : item.label" :prop="item.name">
              <wd-radio-group
                :shape="item.shape"

              @change="({value}: any) => item.handler?.(value)"
                v-model="formState[item.name]" >
                <view style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; justify-content: flex-end;">
                  <wd-radio v-for="option in item.options" checked-color="#07ccc5" :key="option.value" :value="option.value" >
                  {{ option.label }}
                </wd-radio>
                </view>
              </wd-radio-group>
            </wd-cell>


            <wd-cell v-else-if="item.type === 'number'" :title="item.hideLabel ? '' : item.label" :prop="item.name">
              <wd-input-number v-model="formState[item.name]" :min="item.min" :max="item.max" :step="item.step" />

            </wd-cell>


            <wd-col-picker
              v-else-if="item.type === 'pick-address'"
              :immediate-change="true"
              :columns="area"
              :column-change="columnChange"
              :display-format="() => displayFormat(formState[item.name])"
              :label="item.hideLabel ? '' : item.label"
              :prop="item.name"
              v-model="formState[item.name]" />

            <wd-cell  v-else-if="item.type === 'switch'" required :title="item.hideLabel ? '' : item.label"
            :prop="item.name">
              <wd-switch v-model="formState[item.name]" @change="item.handler" active-color="#07ccc5" />
            </wd-cell>


          </div>
          <wd-button v-if="canDelete" @click="() => handleDelete(item, inx)" text>删除</wd-button>
        </wd-cell-group>
      </wd-form>
      <div v-else style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
        <div style="font-size: 14px; color: #999999;">当前{{ title || '表单' }}为空</div>
      </div>
    </div>
    <div class="form-bts">
      <wd-button v-if="!hideOk" :loading="okLoading" block custom-class="form-bts-item" @click="handleOk">
        <div class="form-bts-ok">{{ textOk || '确定' }}</div>
      </wd-button>
    </div>
  </view>

</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { isNil } from 'lodash';
import { useColPickerData } from '@/hooks/useColPickerData';
import { useGlobal } from '@/hooks/useGlobal';

const { toast } = useGlobal();


const { colPickerData, findChildrenByCode } = useColPickerData(['西藏', '新疆', '台湾', '香港', '澳门']);

// todo：替换
import avatarImg from '@/static/default_avatar.png';
import { useApi } from '@/hooks/useApi';


const props = defineProps<{
  title?: string;
  canDelete?: boolean;
  minItems?: number;
  items:((
    {
      name: string;
      label: string;
      rule: any[];
      hideLabel?: boolean;
      placeholder?: string;
    }
  ) & (
      {
        type: undefined;
      }
      | {
        type: 'input';
        inputType: 'nickname' | 'text' | 'number' | 'idcard' | 'digit' | 'safe-password' | 'tel',
        bindnicknamereview?: (pass: boolean, timeout: boolean) => Promise<void> | void,
      }
      | {
        type: 'textarea';
        maxlength?: number;
      }
      | {
        type: 'number';
        min?: number;
        max?: number;
        step?: number;
      }
      | {
        type: 'avatar';
        onbindchooseavatar: (ev: any) => void,
      }
      | {
        type: 'image';
        multiple?: boolean;
        limit?: number;
        uploadFile: (filePath: string) => Promise<any> | any;
      }
      | {
        type: 'qrcode';
      }
      | {
        type: 'scan';
        handler: (qrcode?: string) => void;
      }
      | {
        type: 'time-pick';
        handler: (value?: any) => void;
      }
      | {
        type: 'pick';
        options: {
          label: string;
          value: any;
        }[];
        displayFormat?: (value?: any) => string;
        beforeConfirm?: (value: any, resolve: (value: boolean) => void, picker: any) => void;
        handler?: (value?: any) => void;
      }
      | {
        type: 'radio';
        options: {
          label: string;
          value: any;
        }[];
        shape?: 'dot' | 'button' | 'check';
        handler?: (value?: any) => void;
      }
      | {
        type: 'pick-address';
        handler: (value?: any) => void;
      }
      | {
        type: 'switch';
        handler: (value?: any) => void;
      }
    )
  )[];
  onOk?: (values: any) => Promise<void> | void;
  onCancel?: () => Promise<void> | void;
  textOk?: string;
  // 默认false
  hideOk?: boolean;
}>();

const emit = defineEmits<{(e: 'update:items', items: any[]): void;}>();


const area = ref<any[]>([
  colPickerData.map((item) => ({
    value: item.text,
    label: item.text,
    code: item.value,
  })),
]);

const columnChange = ({ selectedItem, resolve, finish }: any) => {
  const areaData = findChildrenByCode(colPickerData, selectedItem.code);
  if (areaData && areaData.length) {
    resolve(areaData.map((item) => ({
      value: item.text,
      label: item.text,
      code: item.value,
    })));
  } else {
    finish();
  }
};

// 格式化方法
const displayFormat = (values: any) => {
  console.log(values);
  return values.join('/');
};

// 小时列表
const hourList = computed(() => {
  const list = [];

  for (let i = 0; i < 24; i++) {
    list.push({
      value: i,
      text: i < 10 ? `0${i}` : String(i),
    });
  }

  return list;
});

// 分钟列表
const minuteList = computed(() => {
  const list = [];

  for (let i = 0; i < 60; i += 1) {
    list.push({
      value: i,
      text: i < 10 ? `0${i}` : String(i),
    });
  }

  return list;
});

// 秒列表
const secondList = computed(() => {
  const list = [];

  for (let i = 0; i < 60; i += 1) {
    list.push({
      value: i,
      text: i < 10 ? `0${i}` : String(i),
    });
  }

  return list;
});

const timePickerColumns = computed(() => [hourList.value, minuteList.value, secondList.value]);


const formRules = computed(() => props.items.reduce((res, current) => {
  if (current.rule) {
    res[current.name] = current.rule.map((item) => {
      if (!isNil(item.required)) {
        item.message = `${current.label}不能为空`;
      }
      if (isNil(item.trigger)) {
        item.trigger = ['change', 'blur'];
      }
      return item;
    });
  }
  return res;
}, {} as any));

const getInitFormState = () => (
  props.items.reduce((res, current) => {
    if (current.type === 'pick-address') {
      res[current.name] = [];
    } else if (current.type === 'switch') {
      res[current.name] = false;
    } else if (current.type === 'image') {
      res[current.name] = [];
    } else {
      res[current.name] = '';
    }
    return res;
  }, {} as any)
);

const formState = ref(getInitFormState());


const okLoading = ref(false);
const cancelLoading = ref(false);
const formRef = ref<any>();

const setOneFormState = (name: string, value: any) => {
  formState.value = {
    ...formState.value,
    [name]: value,
  };
};


const handleOk = async() => {
  okLoading.value = true;
  try {
    const { valid } = (await formRef.value?.validate()) || {};
    if (!valid) {
      throw new Error('表单验证失败');
    }
    await props.onOk?.(formState.value);
  } finally {
    okLoading.value = false;
  }
};

const handleUpload = async(item: any, file: any, formData: any, options: any) => {
  try {
    const url = await item.uploadFile(file.url);
    file.url = url;
    options.onSuccess({ url }, file, formData);
  } catch (error) {
    console.log(error);
    options.onError({ errMsg: '上传失败' }, file, formData);
  }
};

const handleCancel = async() => {
  cancelLoading.value = true;
  try {
    await props.onCancel?.();
  } finally {
    cancelLoading.value = false;
  }
};

const handleDelete = (item: any, inx: number) => {
  if (props.minItems && props.items.length - 1 < props.minItems) {
    toast.value?.error(`最少保留${props.minItems}个`);
    return;
  }
  setOneFormState(item.name, undefined);
  const newItems = props.items.filter((_, index) => index !== inx);
  emit('update:items', newItems);
};


const handleScan = async(handler: (qrcode?: string) => void) => {
  try {
    const res = await uni.scanCode({
      scanType: ['qrCode'],
    });
    console.log(res);
    console.log(res?.result?.length);
    handler(res?.result);
  } catch (error) {
    toast.value?.error('未识别二维码');
  }
};

defineExpose({
  setFormState: (value: any) => {
    formState.value = value;
  },
  setOneFormState,
  getFormState: () => formState.value,
  reset: () => {
    formState.value = getInitFormState();
  },
  validate: () => formRef.value?.validate(),
  formState,
});


</script>
<style lang="scss" scoped>
.form-title {
  position: absolute;
  top: 0px;
  left: 24px;
  font-family: 'alimamashuheiti';
  font-weight: bold;
  font-size: 30px;
  text-stroke: 4px #FFFFFF;
  text-align: left;
  color: linear-gradient(90deg, #4A4A4A 0%, #323232 100%);
  font-style: normal;
  text-transform: none;
  text-shadow: 2px 0 #fff,
    -2px 0 #fff,
    0 2px #fff,
    0 -2px #fff,
    2px 2px #fff,
    -2px -2px #fff,
    2px -2px #fff, -2px 2px #fff;
  z-index: 200;
}

.form-sub-title {
  position: absolute;
  top: 32px;
  left: 24px;
  font-family: 'alimamashuheiti';
  font-size: 20px;
  color: #F0F0F0;
  font-weight: bold;
  text-align: left;
  z-index: 200;
}

.form {
  position: relative;
  top: 0px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  position: relative;
  overflow: visible;
  background-color: #fff;
  margin-bottom: 8px;
  padding: 16px 4px;
  box-sizing: border-box;

  &-item {
    border-bottom: 1px solid #e5e5e5;
  }


  &-content {
    width: 100%;
  }


  .avatar {
    position: relative;
    display: flex;
    justify-content: center;
  }


}

.form-bts {
  display: flex;
  width: 100%;


  &-ok {
    font-size: 18px;
    color: #ffffff;
  }


}


.form-close {
  position: absolute;
  top: 24px;
  right: 8px;
  width: 32px;
  height: 32px;

  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
