<template>
  <a-modal
    v-model:visible="visible"
    title="打印预览"
    width="100%"
    wrap-class-name="full-modal"
    :bodyStyle="{ padding: '10px' }"
    @cancel="emits('update:isShowPrint', false)"
  >
    <div v-if="isGetFormInfo">
      <div class="btn-box">
        <a-button style="color: #606266; font-size: 13px" @click="handlePrint">
          <template #icon>
            <PrinterOutlined />
          </template>
          打印
        </a-button>
      </div>
      <div class="flex justify-center">
        <template v-if="printData?.style === '1' && !!configs?.formProps">
          <SystemForm
            ref="formRef"
            class="print-style1-box print-box"
            v-if="formConfigs.formType == FormType.SYSTEM"
            :systemComponent="configs.systemComponent"
            :isViewProcess="props.disabled"
            :formModel="configs.formModel"
            :workflowConfig="configs"
          />
          <SimpleForm
            ref="formRef"
            v-else-if="formConfigs.formType == FormType.CUSTOM"
            class="print-style1-box print-box"
            :formProps="configs.formProps"
            :formModel="configs.formModel"
            :isWorkFlow="true"
          />
        </template>
        <div :class="`print-style${props.printData?.style}-box print-box`" v-else>
          <template v-for="(item, index) in formInfo" :key="index">
            <TableStyle :item="item" :componentType="item.type" />
          </template>
        </div>
      </div>
    </div>
  </a-modal>
</template>
<script lang="ts" setup>
  import { ref, computed, Ref, StyleValue, provide, inject, onMounted, nextTick } from 'vue';
  import SimpleForm from '/@/components/SimpleForm/src/SimpleForm.vue';
  import TableStyle from './TableStyle.vue';
  import { getUserMulti } from '/@/api/system/user';
  import { getDicItemDetail } from '/@/api/system/dic';
  import { getDepartment } from '/@/api/system/department';
  import { getAreaMulti } from '/@/api/system/area';
  import { getFileList } from '/@/api/system/file';
  import { PrinterOutlined } from '@ant-design/icons-vue';
  import { buildComponentType } from '/@/utils/helper/designHelper';
  import html2canvas from 'html2canvas';
  import printJS from 'print-js';
  import { cloneDeep, isNil } from 'lodash-es';
  import { FormType } from '/@/enums/workflowEnum';
  import { SystemForm } from '/@/components/SystemForm/index';

  const props = defineProps({
    formConfigs: Object,
    printData: Object,
    isShowPrint: Boolean,
    disabled: Boolean,
  });

  const emits = defineEmits(['update:isShowPrint']);
  const configs = ref({
    formProps: {} as any,
    formModel: {},
    systemComponent: {
      functionalModule: '',
      functionName: '',
      functionFormName: '',
    },
    formType: 0 as FormType,
  });
  const formRef = ref();
  const formInfo = ref<any>([]);
  const activeKey = inject<Ref<number>>('tabActiveKey');
  const visible = ref<boolean>(props.isShowPrint);
  const isGetFormInfo = ref(false);
  const borderColorStyle = computed(() => {
    return { 'border-color': `${props.printData?.borderColor} !important` };
  });
  const underlineStyle = computed(() => {
    return { 'border-bottom': props.printData?.underline === '1' ? '1px solid' : 0 };
  });

  provide<Ref<StyleValue>>('borderColorStyle', borderColorStyle);
  provide<Ref<StyleValue>>('underlineStyle', underlineStyle);
  onMounted(async () => {
    configs.value = cloneDeep(props.formConfigs);

    formInfo.value = [];
    if (props.printData?.style !== '1') {
      await changeFormat(configs.value.formProps.schemas, formInfo.value);
    }
    nextTick(() => {
      configs.value.formModel = cloneDeep(props.formConfigs?.formModel);
      formRef.value?.setFieldsValue(configs.value.formModel);
    });

    isGetFormInfo.value = true;
  });

  const handlePrint = async () => {
    const element: HTMLElement = window.document.querySelector(
      `.print-style${props.printData?.style || 1}-box`,
    )!;

    const canvas = await html2canvas(element, {
      backgroundColor: null,
      useCORS: true,
      windowHeight: document.body.scrollHeight,
    });
    const url = canvas.toDataURL();
    printJS({
      printable: url,
      type: 'image',
      documentTitle: '打印',
      style: `@media print { @page {size: auto; margin: 0; } body{margin:0; padding: 0;}}`,
    });
  };
  const changeFormat = async (schemas, info) => {
    if (!configs.value) return;
    const keys = Object.keys(configs.value.formModel);
    for (const item of schemas) {
      if (['tab', 'grid', 'card', 'table-layout'].includes(item.type)) {
        const layoutChildren = {};
        for (let index = 0; index < item.children.length; index++) {
          let name = index;
          switch (item.type) {
            case 'card':
              name = item.componentProps?.title;
              break;
            case 'tab':
              name = item.children[index].name;
              break;
          }
          layoutChildren[name] = [];
          if (item.type === 'table-layout') {
            for (let idx = 0; idx < item.children[index].list.length; idx++) {
              layoutChildren[name][idx] = [];
              await changeFormat(
                item.children[index].list[idx].children,
                layoutChildren[name][idx],
              );
            }
          } else if ((index === activeKey?.value && item.type === 'tab') || item.type !== 'tab') {
            await changeFormat(item.children[index].list, layoutChildren[name]);
          }
        }
        info.push({
          type: item.type,
          value: layoutChildren,
          grid: item.type === 'grid' ? item.children.map((x) => x.span) : '',
        });
      } else if (item.type === 'form') {
        if (keys.includes(item.componentProps.mainKey)) {
          const columns: any[] = [];
          const value: any[] = [];
          for (const sub of configs.value.formModel[item.componentProps.mainKey]) {
            let val = {};
            for (const col of item.componentProps.columns) {
              if (
                Object.keys(sub).includes(col.dataIndex) &&
                (!!col.show || !!col.componentProps.isShow)
              ) {
                if (!columns.map((x) => x.key).includes(col.dataIndex)) {
                  columns.push({
                    title: col.title,
                    key: col.dataIndex,
                    dataIndex: col.dataIndex,
                  });
                }

                val[col.dataIndex] = await changeValue(col, sub[col.dataIndex]);
              }
            }
            value.push(val);
          }

          info.push({
            type: item.type,
            label: item.label,
            value,
            columns,
          });
        }
      } else {
        const isShow = !isNil(item.show) ? item.show : item.componentProps.isShow;
        if (isShow) {
          let value = '';
          if (!isNil(configs.value.formModel[item.field]) || item.type === 'file') {
            let formValue = configs.value.formModel[item.field];
            if (item.type === 'file') formValue = item.defaultValue;
            value = await changeValue(item, formValue);
          }
          info.push({
            label: item.type === 'title' ? item.defaultValue : item.label,
            type: item.type,
            componentProps: item.componentProps,
            value,
          });
        }
      }
    }
  };

  const changeValue = async (item, fieldValue) => {
    const type = item.type ? buildComponentType(item.type) : item.componentType;
    if (isNil(fieldValue)) return fieldValue;
    if (type === 'User' || (type === 'Info' && item.componentProps?.infoType === 0)) {
      const res = await getUserMulti(fieldValue);
      return res?.map((x) => x.name).toString();
    } else if (type === 'Dept' || (type === 'Info' && item.componentProps?.infoType === 1)) {
      const res = await getDepartment(fieldValue);
      return res?.name;
    } else if (type === 'Area') {
      const res = await getAreaMulti(fieldValue);
      return res?.map((x) => x.name).join(' / ');
    } else if (item.componentProps?.datasourceType === 'dic') {
      const res = await getDicItemDetail(
        item.componentProps?.itemId || item.componentProps?.params?.itemId,
        fieldValue,
      );
      return res?.map((x) => x.name).toString();
    } else if (type === 'Upload' || type === 'File') {
      const res = await getFileList({ folderId: fieldValue });
      return res.map((x) => x.fileName).join(',');
    }
    return fieldValue;
  };
</script>
<style lang="less" scoped>
  .btn-box {
    width: 100%;
    text-align: right;
    margin-bottom: 10px;
  }

  .borderClass {
    border: 0 !important;
  }

  .print-box {
    width: 60%;
    padding: 16px;
  }

  .print-style2-box,
  .print-style3-box,
  .print-style4-box {
    margin: 10px 20px;

    :deep(.ant-row) {
      font-size: 16px;
      border: 1px solid !important;

      .ant-col {
        padding: 15px 5px;
      }
    }
  }

  .print-style3-box {
    :deep(.ant-col:last-child) {
      border-left: 0 !important;
    }
  }

  .print-style2-box {
    :deep(.ant-col:first-child) {
      border-right: 1px solid;
    }
  }

  .print-style4-box {
    :deep(.ant-row) {
      border-left: 0 !important;
      border-right: 0 !important;
      border-top: 0 !important;
    }
  }
</style>
<style lang="less">
  .full-modal {
    .ant-modal {
      max-width: 100%;
      top: 0 !important;
      padding-bottom: 0;
      margin: 0;
      height: 100%;
    }

    .ant-modal-content {
      display: flex;
      flex-direction: column;
      min-height: 100%;
    }

    .ant-modal-body {
      flex: 1;
    }

    .ant-modal-footer {
      display: none !important;
    }
  }
</style>
