<script setup lang="ts">
import type { Ref } from 'vue'
import Upload from '@af-mobile-client-vue3/components/core/Uploader/index.vue'
import { Dialog as VanDialog } from 'vant'
import { onBeforeMount, ref } from 'vue'

interface JsonRenderConfig {
  data: Record<string, any>
  content: Array<{
    type: string
    customFunctionForLabel: string
    customFunctionForValue: string
    jsonArrayDataIndex?: string
  }>
  title?: {
    type: string
    value: string
  }
  style?: Record<string, string>
}

// Props
const props = defineProps({
  config: {
    type: Object as () => JsonRenderConfig,
    required: true,
  },
  displayOnly: {
    type: Boolean,
    default: false,
  },
  noPadding: {
    type: Boolean,
    default: false,
  },
  noTopBorder: {
    type: Boolean,
    default: false,
  },
  showTitle: {
    type: Boolean,
    default: true,
  },
  imgPrefix: {
    type: String,
    default: '',
  },
  serverName: {
    type: String,
    default: 'af-system',
  },
})

// Emits
const emit = defineEmits<{
  (e: 'updateImg', data: any): void
  (e: 'update:config', config: JsonRenderConfig): void
}>()

// 状态
const showImgModal = ref(false)
const showImageSrc = ref('')
const receivedFunction: Ref<Array<{
  labelFunction: Function
  valueFunction: Function
}>> = ref([])

// Methods
function checkImg(target: any[]) {
  if (!target)
    return []
  target.forEach((obj) => {
    if (obj.url === undefined)
      obj.url = obj.path

    if (obj.name === undefined) {
      const withOutEndFix = obj.url.split('.')[0]
      const temp = withOutEndFix.split('/')
      obj.name = temp[temp.length - 1]
    }
    if (obj.status === undefined)
      obj.status = 'done'
  })
  return target
}

function setImages(args: any[], item: any, config: any) {
  // 如果基础上传组件在初始化完成后，就调用emit了setImage，此时图片并没有变化，直接返回
  if (args[2] === 'created')
    return

  const result = {
    name: item.f_project,
    data: args[0],
    orignalData: config,
  }
  emit('updateImg', result)
}

function determineCellStyle(labelFunctionReturn: any, color = '#000', borderWidth = '1px') {
  if (labelFunctionReturn.style) {
    // 如果声明了边框颜色
    if (labelFunctionReturn.style.borderColor)
      color = labelFunctionReturn.style.borderColor

    // 如果声明了边框宽度
    if (labelFunctionReturn.style.borderWidth)
      borderWidth = labelFunctionReturn.style.borderWidth
  }

  // 正常边框单元格
  const withBorder = {
    border: `${borderWidth} solid ${color}`,
    padding: '8px',
  }

  // 仅没有上边框单元格
  const NoTopBorder = {
    borderTopStyle: 'none',
    borderLeft: `${borderWidth} solid ${color}`,
    borderRight: `${borderWidth} solid ${color}`,
    borderBottom: `${borderWidth} solid ${color}`,
    padding: '8px',
  }

  let result: any
  // 判断表头是否有声明的样式
  if (labelFunctionReturn.style !== undefined)
    result = props.noTopBorder ? { ...NoTopBorder, ...labelFunctionReturn.style } : { ...withBorder, ...labelFunctionReturn.style }
  else
    result = props.noTopBorder ? { ...NoTopBorder } : { ...withBorder }

  return result
}

function handleShowImgOk() {
  showImgModal.value = false
  showImageSrc.value = ''
}

function handleShowImgCancel() {
  showImgModal.value = false
  showImageSrc.value = ''
}

function openImgModal(img: string) {
  showImageSrc.value = img
  showImgModal.value = true
}

function formatImgName(imgSrc: string) {
  return imgSrc.split('/').pop() || ''
}

// 生命周期
onBeforeMount(() => {
  // 遍历配置，将所有JSON传递的方法保存到一个数组中，并用index来一一对应
  for (let i = 0; i < props.config.content.length; i++) {
    receivedFunction.value.push({
      // eslint-disable-next-line no-new-func
      labelFunction: new Function(`return ${props.config.content[i].customFunctionForLabel}`)(),
      // eslint-disable-next-line no-new-func
      valueFunction: new Function(`return ${props.config.content[i].customFunctionForValue}`)(),
    })
  }
})
</script>

<template>
  <div id="xreportjsonrender" :class="noPadding ? 'reportMainNoPadding' : 'reportMain'">
    <table class="reportTable" :style="config.style ? config.style : ''">
      <tbody class="'reportTable'">
        <!--   标题   -->
        <tr v-if="showTitle && config.title.type && config.title.type !== ''">
          <td :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'" colspan="12">
            <template v-if="config.title.type === 'titleKey'">
              {{ config.data[config.title.value] }}
            </template>
            <template v-else-if="config.title.type === 'titleValue'">
              {{ config.title.value }}
            </template>
          </td>
        </tr>
        <template v-for="(row, rowIndex) in config.content">
          <!--     数据对象是一个Obj     -->
          <template v-if="row.type === 'jsonKey'">
            <tr :key="rowIndex">
              <!--      表头        -->
              <td
                :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
                :style="determineCellStyle(receivedFunction[rowIndex].labelFunction(config, row))"
                colspan="6"
              >
                <template v-if="receivedFunction[rowIndex].labelFunction(config).type === 'key'">
                  {{ config.data[receivedFunction[rowIndex].labelFunction(config).content] }}
                </template>
                <template v-else-if="receivedFunction[rowIndex].labelFunction(config).type === 'value'">
                  {{ receivedFunction[rowIndex].labelFunction(config).content }}
                </template>
              </td>
              <!--      内容        -->
              <td
                :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
                :style="determineCellStyle(receivedFunction[rowIndex].valueFunction(config))"
                colspan="6"
              >
                <template v-if="displayOnly">
                  <template v-if="receivedFunction[rowIndex].valueFunction(config).type === 'key'">
                    {{ config.data[receivedFunction[rowIndex].valueFunction(config).content] }}
                  </template>
                  <template v-else-if="receivedFunction[rowIndex].valueFunction(config).type === 'value'">
                    {{ receivedFunction[rowIndex].valueFunction(config).content }}
                  </template>
                </template>
                <template v-else>
                  <template v-if="receivedFunction[rowIndex].valueFunction(config).originalKey">
                    <van-field
                      :value="config.data[receivedFunction[rowIndex].valueFunction(config).originalKey]"
                      @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config).originalKey]: val } })"
                    />
                  </template>
                  <template v-else>
                    <van-field
                      :value="config.data[receivedFunction[rowIndex].valueFunction(config).content]"
                      @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config).content]: val } })"
                    />
                  </template>
                </template>
                <template v-if="receivedFunction[rowIndex].valueFunction(config).type === 'img'">
                  <template v-for="(img, imgIndex) in receivedFunction[rowIndex].valueFunction(config).content" :key="imgIndex">
                    <span class="imgText">
                      <van-icon type="link" />
                      <span @click="openImgModal(img)">{{ formatImgName(img) }}</span>
                      <br>
                    </span>
                  </template>
                </template>
              </td>
            </tr>
          </template>
          <!--     数据对象是一个Array     -->
          <template v-else-if="row.type === 'jsonArray'">
            <tr v-for="(item, jsonArrayItemIndex) in config.data[row.jsonArrayDataIndex]" :key="`${rowIndex}${jsonArrayItemIndex}`">
              <!--      表头        -->
              <td
                :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
                :style="determineCellStyle(receivedFunction[rowIndex].labelFunction(config, item))"
                colspan="6"
              >
                <template v-if="receivedFunction[rowIndex].labelFunction(config, item).type === 'key'">
                  {{ item[receivedFunction[rowIndex].labelFunction(config, item).content] }}
                </template>
                <template v-if="receivedFunction[rowIndex].labelFunction(config, item).type === 'value'">
                  {{ receivedFunction[rowIndex].labelFunction(config, item).content }}
                </template>
              </td>
              <!--      内容        -->
              <td
                :class="noTopBorder ? 'tdWithNoTopBorder' : 'tdWithBorder'"
                :style="determineCellStyle(receivedFunction[rowIndex].valueFunction(config, item))"
                colspan="6"
              >
                <template v-if="displayOnly">
                  <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'key'">
                    {{ item[receivedFunction[rowIndex].valueFunction(config, item).content] }}
                  </template>
                  <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'value'">
                    {{ receivedFunction[rowIndex].valueFunction(config, item).content }}
                  </template>
                  <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'imgs'">
                    <template v-if="!item.imgs || item.imgs.length === 0">
                      <p style="margin: auto">
                        无
                      </p>
                    </template>
                    <template v-else>
                      <template v-for="(img, imgIndex) in item.imgs" :key="imgIndex">
                        <div>
                          <img :src="img.path" style="max-width: 200px; max-height: 200px">
                          <p style="margin: auto">
                            {{ img.path.substring(img.path.lastIndexOf('/') + 1, img.path.lastIndexOf('.')) }}
                          </p>
                        </div>
                      </template>
                    </template>
                  </template>
                </template>
                <template v-else>
                  <template v-if="receivedFunction[rowIndex].valueFunction(config, item).originalKey">
                    <template v-if="receivedFunction[rowIndex].valueFunction(config, item).type === 'imgs'">
                      <Upload
                        :model="{
                          type: 'image',
                          accept: ['*'],
                          resUploadStock: 1,
                          pathKey: 'cs',
                        }"
                        :outer-container-index="1"
                        :img-prefix="imgPrefix"
                        :service-name="serverName"
                        :images="checkImg(item.imgs)"
                        upload-style="simple"
                        @set-files="(...args) => { setImages(args, item, config.data) }"
                      />
                    </template>
                    <template v-else>
                      <van-field
                        :value="item[receivedFunction[rowIndex].valueFunction(config, item).originalKey]"
                        @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config, item).originalKey]: val } })"
                      />
                    </template>
                  </template>
                  <template v-else>
                    <van-field
                      :value="item[receivedFunction[rowIndex].valueFunction(config, item).content]"
                      @input="(val) => emit('update:config', { ...config, data: { ...config.data, [receivedFunction[rowIndex].valueFunction(config, item).content]: val } })"
                    />
                  </template>
                </template>
              </td>
            </tr>
          </template>
        </template>
      </tbody>
    </table>
    <!--  图片展示弹框  -->
    <VanDialog
      v-model:show="showImgModal"
      title="图片"
      width="80%"
      :z-index="1001"
      @confirm="handleShowImgOk"
      @cancel="handleShowImgCancel"
    >
      <div style="width: 100%;display: flex;justify-content: center;align-items: center">
        <img :src="showImageSrc" alt="图片">
      </div>
    </VanDialog>
  </div>
</template>

<style scoped lang="less">
.imgSrc {
  color: rgb(24, 144, 255);
  font-size: 0.9em;
  margin: auto;
}
.imgSrc:hover {
  color: rgba(24, 144, 255, 0.8);
  font-size: 0.9em;
  cursor: pointer;
}
.reportMain {
  text-align: center;
  margin: 0 auto;
  font-size: 16px;
  color: #000;
  background-color: #fff;
  border-radius: 8px;
}

.reportMainNoPadding {
  text-align: center;
  margin: 0 auto;
  font-size: 16px;
  color: #000;
  background-color: #fff;
  border-radius: 8px;
}

.reportTitle {
  font-weight: bold;
}

.reportTable {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  word-break: break-all;
}

.tdWithBorder {
  border: 1px solid #000;
  padding: 8px;
}

.imgText:hover {
  color: rgb(24, 144, 255);
  cursor: pointer;
}

.tdWithNoTopBorder {
  border-top-style: none;
  border-left: 1px solid #000;
  border-right: 1px solid #000;
  border-bottom: 1px solid #000;
  padding: 8px;
}
</style>
