<template>
  <a-input
    :style="{ width: width }"
    v-model:value="value"
    :placeholder="placeholder"
    :addonBefore="addonBefore"
    :addonAfter="addonAfter"
    :disabled="disabled"
    readonly
    v-if="!usersInfo.length"
  >
    <template #prefix v-if="prefix">
      <Icon :icon="prefix" />
    </template>
    <template #suffix v-if="suffix">
      <Icon :icon="suffix" />
    </template>
  </a-input>
  <div class="flex flex-wrap" :style="{ width: width }" v-else>
    <div
      v-for="item in usersInfo"
      :key="item.id"
      :class="['user-box', disabled ? 'pointer-events-none' : '']"
      :disabled="disabled"
      @click="showSign(item)"
    >
      <img :src="item.imgUrl" v-if="item.imgUrl" />
      <div class="text-center" v-else>
        <div>{{ item.name }}</div>
        <div class="mt-1.5">点击签名</div>
      </div>
    </div>
  </div>
  <a-modal
    v-model:visible="visible"
    :width="600"
    :bodyStyle="{ height: '436px' }"
    :title="t('签名')"
    @ok="confirm"
    @cancel="cancel"
  >
    <a-form-item-rest>
      <a-radio-group v-model:value="signType" name="radioGroup" v-if="isCallSign" class="radio-box">
        <a-radio value="write">{{ t('手写签名') }}</a-radio>
        <a-radio value="sign">{{ t('签章') }}</a-radio>
      </a-radio-group>
      <vue-esign
        v-if="visible && ((isCallSign && signType === 'write') || !isCallSign)"
        ref="canvas"
        :width="600"
        :height="436"
        :isCrop="signInfo.isCrop"
        :lineWidth="signInfo.lineWidth"
        :lineColor="signInfo.lineColor"
        v-model:bgColor="signInfo.bgColor"
      />

      <div v-if="signType === 'sign'" class="m-5">
        <a-select
          v-model:value="signFileUrl"
          :placeholder="t('请选择签章')"
          allowClear
          :options="signOptions"
          :fieldNames="{ label: 'name', value: 'fileUrl' }"
          :style="{ width: '90%' }"
        />
      </div>
    </a-form-item-rest>
  </a-modal>
</template>
<script lang="ts" setup>
  import { ref, watch, inject, onMounted, reactive, computed } from 'vue';
  import vueEsign from 'vue-esign';
  import { message } from 'ant-design-vue';
  import { Icon } from '/@/components/Icon';
  import { getUserMulti } from '/@/api/system/user';
  import { uploadBlobApi } from '/@/api/sys/upload';
  import { getStampPage } from '/@/api/workflow/stamp';
  import { StampInfo } from '/@/api/workflow/model/index';
  import { dataURLtoBlob } from '/@/utils/file/base64Conver';
  import { StampType } from '/@/enums/workflowEnum';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { FormSchema } from '/@/components/Form/src/types/form';
  import { getRoleMulti } from '/@/api/system/role';
  import { useUserStore } from '/@/store/modules/user';
  import { useMessage } from '/@/hooks/web/useMessage';

  const userStore = useUserStore();
  const { createMessage } = useMessage();
  interface UserInfo {
    id: string;
    name: string;
    imgUrl?: string;
  }
  const { t } = useI18n();

  const props = defineProps({
    value: {
      type: String,
      default: '',
    },
    defaultValue: {
      type: String,
      default: '',
    },
    associateComponents: {
      type: Array,
      default: () => [],
    },
    addonBefore: String,
    addonAfter: String,
    prefix: String,
    suffix: String,
    disabled: Boolean,
    isCallSign: Boolean,
    signValueType: Number,
    width: String,
  });
  const emit = defineEmits(['update:value']);

  const formModel = inject<any>('formModel', null);
  const formProps = inject<any>('formProps', null);

  const usersInfo = ref<UserInfo[]>([]);
  const assoArr = ref<any[]>([]);
  const value = ref('');
  const visible = ref<boolean>(false);
  const canvas = ref();
  const currentUser = ref();
  const assoComponents = ref<FormSchema[]>([]);
  const signType = ref<string>('write');
  const signOptions = ref<StampInfo[]>([]);
  const signFileUrl = ref('');
  // const isImmediate = ref(false);

  const signInfo = reactive({
    lineWidth: 6,
    lineColor: '#000000',
    bgColor: '',
    resultImg: '',
    isCrop: false,
  });

  watch(
    () => formModel,
    (val) => {
      // if (!props.isCallSign) {
      if (props.associateComponents?.length) {
        assoComponents.value?.map((item) => {
          if (val[item.field!] !== undefined) {
            getAssoComponentInfo();
          }
        });
      }
      // }
    },
    {
      deep: true,
    },
  );

  watch(
    () => props.value,
    async (val) => {
      // if (isImmediate.value) return;
      //编辑时获取值调用
      if (isJSON(val)) {
        let userIds: string[] = [];
        userIds = Object.keys(JSON.parse(val));
        if (userIds.length) {
          // getAssoComponentInfo(userIds);
          // if (props.signValueType === 0) {
          //   usersInfo.value = await getRoleMulti([...new Set(userIds)].toString());
          // } else {
          //   usersInfo.value = await getUserMulti([...new Set(userIds)].toString());
          // }
          if (val) {
            usersInfo.value.forEach((item) => {
              item.imgUrl = JSON.parse(val)[item.id];
            });
          }
        }
      }
      //isImmediate.value = true;
    },
    {
      deep: true,
    },
  );

  const placeholder = computed(() => {
    if (assoComponents.value?.length) {
      let str = '请先选择';
      assoComponents.value?.forEach((item, idx) => {
        if (idx + 1 === assoComponents.value.length) {
          str = str.concat(`"${item.label}"后再进行签名！`);
        } else {
          str = str.concat(`"${item.label}"、`);
        }
      });
      return str;
    }
    return '请选择签字人';
  });

  onMounted(async () => {
    // if (props.defaultValue && props.signValueType === 0) {
    //   usersInfo.value = await getRoleMulti(props.defaultValue);
    // } else if (props.defaultValue) {
    //   usersInfo.value = await getUserMulti(props.defaultValue);
    // } else if (props.associateComponents?.length) {
    //   getSignAssoComponents(formProps?.value.schemas);
    //   assoArr.value = assoComponents.value?.map((item) => {
    //     return { type: item.type, field: item.field };
    //   });
    // }

    if (props.isCallSign) {
      getOptions();
    }
    //else {
    if (props.associateComponents?.length) {
      getSignAssoComponents(formProps?.value.schemas);
      assoArr.value = assoComponents.value?.map((item) => {
        return { type: item.type, field: item.field };
      });
    }
    getAssoComponentInfo();
    // }
  });

  function isJSON(str) {
    try {
      JSON.parse(str);
    } catch (e) {
      return false;
    }
    return true;
  }

  const getSignAssoComponents = (list) => {
    list.forEach((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.children!) {
          getSignAssoComponents(child.list);
        }
      } else if (item.type === 'table-layout') {
        for (const child of item.children!) {
          for (const item2 of child.list) {
            getSignAssoComponents(item2.children);
          }
        }
      } else if (props.associateComponents.includes(item.key)) {
        assoComponents.value!.push(item);
      }
    });
  };

  const getAssoComponentInfo = async () => {
    usersInfo.value = [];
    let assoUsers: string[] = [];
    let assoRoles: string[] = [];
    assoArr.value.forEach((item) => {
      if (formModel[item.field]) {
        if (item.type == 'role') {
          assoRoles.push(...formModel[item.field]?.split(','));
        } else {
          assoUsers.push(...formModel[item.field]?.split(','));
        }
      }
    });
    const defaultValue = props.defaultValue ? props.defaultValue?.split(',') : '';
    let userIds = [...assoUsers],
      roleIds = [...assoRoles];
    if (props.signValueType === 1) {
      userIds = [...new Set([...assoUsers, ...defaultValue])];
    }
    if (props.signValueType === 0) {
      roleIds = [...new Set([...assoRoles, ...defaultValue])];
    }
    if (usersInfo.value.length === userIds.length + roleIds.length) {
      const usersInfoIds = usersInfo.value.map((x) => x.id);
      if ([...userIds, ...roleIds].every((x) => usersInfoIds.includes(x))) return;
    }

    let infoData: any = [];
    if (userIds.length > 0) {
      let res = await getUserMulti(userIds.toString());
      infoData = res || [];
    }
    if (roleIds.length > 0) {
      let res = await getRoleMulti(roleIds.toString());
      let data = res || [];
      infoData = [...infoData, ...data];
    }
    usersInfo.value = infoData;

    if (typeof props.value === 'string' && props.value) {
      const valueObj = JSON.parse(props.value);
      if (props.value && valueObj && Object.keys(valueObj).length) {
        for (let key in valueObj) {
          usersInfo.value.forEach((item) => {
            if (item.id === key) {
              item.imgUrl = valueObj[key];
            }
          });
        }
      }
    }
    if (usersInfo.value.length) {
      let val = {};
      usersInfo.value.forEach((item) => {
        val[item.id] = item.imgUrl || '';
      });
      emit('update:value', JSON.stringify(val));
    }
  };

  const showSign = (item) => {
    let hasId = [userStore.getUserInfo.id];
    userStore.getUserInfo.roles.forEach((o) => {
      hasId.push(o.id);
    });
    if (hasId.includes(item.id)) {
      currentUser.value = item;
      visible.value = true;
    } else {
      createMessage.warning('你不是' + item.name + '，不能签名！');
    }
  };

  async function getOptions() {
    const data = await getStampPage(StampType.PRIVATE_SIGNATURE, {
      limit: 1,
      size: 100,
    });
    signOptions.value = data?.list || [];
  }

  function cancel() {
    if (signType.value === 'write') {
      canvas.value.reset();
    }
    signType.value = 'write';
  }

  async function confirm() {
    let url = '';
    if (signType.value === 'write') {
      try {
        const res = await canvas.value.generate();
        if (res) {
          const blob = dataURLtoBlob(res);
          const fileUrl = await uploadBlobApi(blob, t('手写签名.png'));
          if (fileUrl) {
            url = fileUrl;
            message.success(t('手写签名上传成功'));
          } else {
            message.error(t('手写签名上传失败'));
          }
        }
      } catch (error) {
        console.log('error', error);
      }
    } else {
      url = signFileUrl.value;
    }
    currentUser.value.imgUrl = url;
    const emitValue = {};
    usersInfo.value.forEach((item) => {
      emitValue[item.id] = item.imgUrl || '';
    });
    emit('update:value', JSON.stringify(emitValue));
    visible.value = false;
  }
</script>
<style lang="less" scoped>
  .user-box {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 110px;
    height: 80px;
    border: 1px dashed #ccc;
    border-radius: 5px;
    margin-right: 7px;
    margin-bottom: 7px;
    background-color: #f6f8fa;
    cursor: pointer;
    color: #6f7075;

    &:hover {
      border: 1px dashed #6d9fff;
    }
  }

  .radio-box {
    display: flex;
    justify-content: center;
    margin-top: 15px;
  }
</style>
