<template>
  <div class="flex h-full">
    <div id="luckysheet" class="flex-1"></div>

    <el-scrollbar height="100%">
      <div class="w-[420px] h-full bg-white">
        <p class="pl-2 text-lg font-bold leading-[40px] bg-slate-200">标注配置</p>
        <SetArea @success="onSaveSuccess" :areaTypeLen="areaTypeLen" />
        <div class="pl-2 pb-2">
          <el-button type="primary" size="small" @click="setProdCompare">设置产品对照</el-button>
          <el-button type="primary" size="small" @click="deletePic">删除图片</el-button>
        </div>

        <div class="pt-2 pl-2 pr-2 pb-2 text-sm border-t-2 border-b-2">
          <p class="font-bold">标记区域</p>
          <vxe-table
            @cell-click="cellClick"
            :row-config="{ isCurrent: true }"
            border
            :data="areaList"
            size="mini"
            height="200"
          >
            <vxe-column title="sheet" field="sheetNum" width="55"></vxe-column>
            <vxe-column title="别称" field="excelAreaNicname"></vxe-column>
            <vxe-column title="类型" field="excelAreaType_dictText" width="60"></vxe-column>
            <vxe-column title="区域" field="area" width="80">
              <template #default="{ row }">
                {{ getRangetxt(row.beginRow, row.endRow, row.beginColum, row.endColum) }}
              </template>
            </vxe-column>
            <vxe-column title="操作" field="action" width="100">
              <template #default="{ row }">
                <el-link
                  class="mr-1"
                  style="font-size: 12px"
                  type="primary"
                  @click.stop="chooseConnect(row)"
                  >关联</el-link
                >
                <el-link
                  class="mr-1"
                  style="font-size: 12px"
                  type="primary"
                  @click.stop="toModify(row)"
                  >修改</el-link
                >
                <el-link style="font-size: 12px" type="danger" @click.stop="delAreaMark(row)"
                  >删除</el-link
                >
              </template>
            </vxe-column>
          </vxe-table>
        </div>

        <div class="p-2 text-sm">
          <p class="font-bold">区域关联信息</p>
          <vxe-table border :data="connectList" size="mini" height="200">
            <vxe-column title="关联名称" field="excelAreaId_dictText"></vxe-column>
            <vxe-column title="别关联名称" field="excelAreaBeId_dictText"></vxe-column>
            <vxe-column title="操作" field="action" width="80">
              <template #default="{ row, $rowIndex }">
                <el-link style="font-size: 12px" type="danger" @click="delConnect(row, $rowIndex)"
                  >删除</el-link
                >
              </template>
            </vxe-column>
          </vxe-table>
        </div>

        <div class="p-2 text-sm">
          <p class="font-bold">产品对照</p>
          <vxe-table border :data="compareData" show-overflow="tooltip" size="mini" height="300">
            <vxe-column field="productId_dictText" title="产品名称" width="200"></vxe-column>
            <vxe-column field="customerId_dictText" title="客户名称" width="200"></vxe-column>
            <vxe-column field="excelFiled" title="产品描述" width="200"></vxe-column>
            <vxe-column title="操作" width="50">
              <template #default="{ row }">
                <el-link type="danger" style="font-size: 12px" @click="toDelete(row)">删除</el-link>
              </template>
            </vxe-column>
          </vxe-table>

          <vxe-pager
            size="small"
            background
            v-model:current-page="compareParams.currentPage"
            v-model:page-size="compareParams.pageSize"
            :total="compareParams.total"
            @page-change="getCompareList"
            :layouts="['PrevPage', 'JumpNumber', 'NextPage', 'Sizes', 'Total']"
          >
          </vxe-pager>
        </div>

        <el-button type="primary" size="small" @click="toRun">执行解析</el-button>
      </div>
    </el-scrollbar>

    <vxe-modal width="80%" height="600" v-model="editVisible" title="编辑区域" show-footer>
      <EditArea ref="editAreaRef" :current-area-mark="currentAreaMark" />
      <template #footer>
        <el-button type="primary" @click="confirmEdit">提交</el-button>
      </template>
    </vxe-modal>

    <vxe-modal
      width="600"
      @hide="chooseConnectOnHide"
      v-model="chooseVisible"
      title="选择被关联的区域"
      show-footer
    >
      <vxe-table ref="beConnectTable" border size="mini" :data="beConnectData" height="400">
        <vxe-column type="radio" width="40"></vxe-column>
        <vxe-column title="sheet" field="sheetNum" width="60"></vxe-column>
        <vxe-column title="别称" field="excelAreaNicname"></vxe-column>
        <vxe-column title="区域类型" field="excelAreaType_dictText" width="100"></vxe-column>
        <vxe-column title="区域" field="area" width="90">
          <template #default="{ row }">
            {{ getRangetxt(row.beginRow, row.endRow, row.beginColum, row.endColum) }}
          </template>
        </vxe-column>
      </vxe-table>

      <template #footer>
        <el-button type="primary" @click="confirmBeConnect">确认</el-button>
      </template>
    </vxe-modal>

    <vxe-modal v-model="connectVisible" width="700" title="关联信息配置" show-footer>
      <p>关联区域信息：{{ currentConnectInfo.excelAreaNicname }}</p>
      <p>被关联信息：{{ cachCurrentBeConnectInfo.excelAreaNicname }}</p>

      <vxe-table
        class="mt-2"
        size="mini"
        :data="connectConfigData"
        border
        height="400"
        ref="xTableConnect"
      >
        <vxe-column type="checkbox" width="40"></vxe-column>
        <vxe-column title="关联title" field="title"></vxe-column>
        <vxe-column title="被关联title" field="betitle">
          <template #default="{ row }">
            <el-select v-model="row.betitle" size="small" @change="(v) => changeBeConnect(v, row)">
              <template v-for="item in beConnectSelectOptions" :key="item.title">
                <el-option :value="item.title" :label="item.title"></el-option>
              </template>
            </el-select>
          </template>
        </vxe-column>
      </vxe-table>
      <template #footer>
        <el-button type="primary" @click="confirmConnect">确认</el-button>
      </template>
    </vxe-modal>

    <vxe-modal width="80%" title="解析结果" v-model="runResultVisible">
      <el-button @click="exportRunData">导出数据</el-button>
      <vxe-table
        ref="runDataTable"
        size="mini"
        show-overflow="tooltip"
        show-header-overflow="tooltip"
        :data="runResultData"
        border
        height="500"
      >
        <vxe-column title="行号" width="120">
          <template #default="{ row }">{{ row.sortNum }}</template>
          <!-- <template #content="{ row, rowIndex }">
            <div style="padding: 10px">
              <template v-for="attchName of filterObjKeys(row.expendData)">
                <p>{{ attchName }}</p>
                <vxe-table
                  :data="row.expendData[attchName]"
                  header-row-class-name="expandTableHeader"
                  min-height="82"
                  height="82"
                  size="mini"
                  show-overflow="tooltip"
                  show-header-overflow="tooltip"
                  style="width: 70vw;"
                  border
                >
                  <vxe-column
                    v-for="key in filterObjKeys(row.expendData[attchName][0])"
                    :title="key"
                    :field="key"
                    width="140"
                  ></vxe-column>
                </vxe-table>
              </template>
            </div>
          </template> -->
        </vxe-column>
        <vxe-column title="sheet页" width="120">
          <template #default="{ row }">{{ row['sheet页'] }}</template>
        </vxe-column>
        <vxe-column title="数据区" width="120">
          <template #default="{ row }">{{ row['数据区'] }}</template>
        </vxe-column>
        <template v-for="item in runResultTitle" :key="item">
          <vxe-column :title="item" :field="item" width="200"></vxe-column>
        </template>
      </vxe-table>
    </vxe-modal>

    <ProductCompare v-model:visible="showProdCompare" @success="getCompareList" />
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, onUnmounted, reactive, unref, computed, watch, nextTick } from 'vue'
import LuckyExcel from 'luckyexcel'
import ProductCompare from '../ProductCompare/ProductCompare.vue'
import SetArea from '../SetArea/SetArea.vue'
import {
  areaMarksColor,
  authorityConfig,
  cellRightClickConfig,
  sheetRightClickConfig,
  showsheetbarConfig,
  showstatisticBarConfig
} from '@/constants/excelConfig'
import { flatten, cloneDeep } from 'lodash-es'
import { useCommentExcel } from '@/stores/commentExcel'
import { storeToRefs } from 'pinia'
import { isFunction } from '@/utils/is'
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import {
  addExcelAreaConnect,
  editExcelArea,
  excelMarkRun,
  getExcelAreaByFileId,
  getExcelConnectByFileId,
  removeExcelArea,
  removeExcelAreaConnect
} from '@/api/excel'
import type { Recordable } from '@/types/global'
import { filterRunData, getRangetxt, setRangeBackground } from '@/utils/excel'
import type { VxeTableInstance } from 'vxe-table'
import EditArea from '../EditArea/EditArea.vue'
import { deleteExcelProdFileConfByIds, getExcelProdFileConfPage } from '@/api/product'

const connectVisible = ref(false)
const showProdCompare = ref(false)
const xTableConnect = ref<VxeTableInstance>()
const beConnectTable = ref<VxeTableInstance>()
const compareData = ref([])
const compareParams = reactive({
  pageSize: 10,
  currentPage: 1,
  total: 0,
  customerId: ''
})
const luckysheet = (window as any).luckysheet
const commentExcelStore = useCommentExcel()
const { getFileInfo } = storeToRefs(commentExcelStore)
const connectList = ref<any[]>([])
const chooseVisible = ref(false)
const editVisible = ref(false)
const currentConnectInfo = reactive<Recordable>({
  excelAreaConnectId: '',
  excelAreaId: '',
  excelAreaBeId: '',
  connectFiled: [],
  beConnectFiled: [],
  fileId: ''
})
const runDataTable = ref<VxeTableInstance>()
const cachCurrentConnectInfo = reactive<Recordable>({})
const cachCurrentBeConnectInfo = reactive<Recordable>({})
const beConnectData = computed(() => {
  /**
   * 如果公共区域 和 附加区域关联 只能关联 数据区域
   *
   * 并且数据区不能关联数据区
   */
  if (cachCurrentConnectInfo.excelAreaType == 'data_area') {
    return areaList.value
      .filter((v) => v.excelAreaType != 'data_area')
      .filter((v: any) => v.excelAreaId != currentConnectInfo.excelAreaId)
  } else {
    return areaList.value
      .filter((v) => v.excelAreaType == 'data_area')
      .filter((v: any) => v.excelAreaId != currentConnectInfo.excelAreaId)
  }
})

const isSetSheetMark = ref<any>([])
const initIsSetSheetMark = (length: number) => {
  isSetSheetMark.value = Array.from({ length }).fill(false)
}

/**
 * 存储在本地的区域标记
 * locaExcelAreaMarks = {
 *  '0': [formState, formState]
 * }
 */
const locaExcelAreaMarks: Recordable = reactive({})
const areaList = computed(() => flatten(Object.values(locaExcelAreaMarks)))
const areaTypeLen = computed(() => {
  return areaList.value.reduce(
    (pre, cur) => {
      pre[cur.excelAreaType] += 1
      return pre
    },
    {
      data_area: 0,
      public_area: 0,
      attach_area: 0
    }
  )
})
const deletePic = () => {
  luckysheet.deleteImage()
}
const initExcelAreaMarksKey = (len: number) => {
  Array.from({ length: len }).forEach((item, index) => {
    Reflect.set(locaExcelAreaMarks, index, [])
  })
}
const onSaveSuccess = (data: any) => {
  locaExcelAreaMarks[data.result['sheetNum']].push(data.result)
}

const exportRunData = () => {
  runDataTable.value?.exportData({ type: 'csv' })
}

const setProdCompare = () => {
  showProdCompare.value = true
}

const setSheetAuthority = (exportJson: any) => {
  exportJson.sheets.forEach((sheet: any) => {
    // 工作表格权限
    sheet.config.authority = authorityConfig
    // 单元格锁定
    sheet.celldata.forEach((item: any) => {
      item.v.lo = 1
    })
  })
}

const cellClick = ({ row }) => {
  let sheetNum: number, beginRow: number, beginColum: number, endColum: number, endRow: number
  const flag = row.sheetNum !== undefined
  sheetNum = flag ? row.sheetNum : row.sheet
  beginRow = flag ? row.beginRow : row.row
  beginColum = flag ? row.beginColum : row.colum
  endColum = flag ? row.endColum : row.colum
  endRow = flag ? row.endRow : row.row
  // 判断是否是当前sheet页标记
  const sheet = luckysheet.getSheet()
  if (sheet.order != sheetNum) {
    luckysheet.setSheetActive(sheetNum)
  }
  luckysheet.scroll({
    targetRow: beginRow - 3 < 0 ? 0 : beginRow - 3,
    targetColumn: beginColum - 3 < 0 ? 0 : beginColum - 3
  })
  luckysheet.setRangeShow({
    row: [beginRow, endRow],
    column: [beginColum, endColum]
  })
}

const delAreaMark = async (row: any) => {
  // 判断当前区域是否关联了其他区域
  if (
    connectList.value.find(
      (v) => row.excelAreaId == v.excelAreaId || row.excelAreaId == v.excelAreaBeId
    )
  ) {
    return ElMessage.warning('当前区域绑定与其他区域绑定了关联信息，请先删除关联信息之后再做修改！')
  }

  // 调用接口删除
  await removeExcelArea(row.excelAreaId)
  const sheet = luckysheet.getSheet()
  /**
   * 如果在本sheet那么直接删除，并且清除区域颜色
   * 不在当前sheet页，切换sheet显示页
   */
  if (row.sheetNum == sheet.order) {
  } else {
    luckysheet.setSheetActive(row.sheetNum)
  }
  const range: Recordable = {
    row: [row.beginRow, row.endRow],
    column: [row.beginColum, row.endColum]
  }
  luckysheet.setRangeShow(range)
  luckysheet.setRangeFormat('bg', areaMarksColor['default'])

  // 删除本地标记 locaExcelAreaMark[row.sheetNum] 对应的区域
  const index = locaExcelAreaMarks[row.sheetNum].findIndex(
    (item: any) => item.excelAreaId == row.excelAreaId
  )
  locaExcelAreaMarks[row.sheetNum].splice(index, 1)
}

const editAreaRef = ref()
const currentAreaMark = reactive({})
const toModify = (row) => {
  // 判断当前区域是否关联了其他区域
  if (
    connectList.value.find(
      (v) => row.excelAreaId == v.excelAreaId || row.excelAreaId == v.excelAreaBeId
    )
  ) {
    return ElMessage.warning('当前区域绑定与其他区域绑定了关联信息，请先删除关联信息之后再做修改！')
  }

  Object.assign(currentAreaMark, cloneDeep(row))
  editVisible.value = true
}
const confirmEdit = async () => {
  const areaData = editAreaRef.value.getAreaData()
  const delCapAndExc = editAreaRef.value.getDelCapAndExc()
  const { data } = await editExcelArea(areaData)
  if (data.code == 200) {
    if (delCapAndExc.length) {
      delCapAndExc.forEach((item: any) => {
        setRangeBackground(item, areaMarksColor[item.type == 1 ? 'default' : 'data'])
      })
    }
    ElMessage.success('修改成功！')
    editVisible.value = false

    const idx = locaExcelAreaMarks[areaData['sheetNum']].findIndex((item: any) => {
      return item.excelAreaId == areaData.excelAreaId
    })
    locaExcelAreaMarks[areaData['sheetNum']].splice(idx, 1, areaData)
    // Object.assign()
  } else {
    return ElMessage.error(data.message)
  }
}

const queryArea = async () => {
  const { data } = await getExcelAreaByFileId(getFileInfo.value.orderFileId)
  data.result.forEach((item: any) => locaExcelAreaMarks[item.sheetNum || 0].push(item))
}
const confirmConnect = () => {
  /**
   * 1. 验证是否选择了要关联的title
   * 2. 验证选择的title是否有被关联的title
   * 3. 添加关联关系
   */

  const list = xTableConnect.value?.getCheckboxRecords()
  if (!list?.length) {
    if (
      cachCurrentConnectInfo.excelAreaType == 'attach_area' ||
      cachCurrentBeConnectInfo.excelAreaType == 'attach_area'
    ) {
      return ElMessage.warning('请选择关联的字段！')
    }
    addConnect([])
    return
  }

  try {
    list.forEach((item) => {
      if (!item.betitle) {
        throw new Error('请选择被关联的title！！')
      }
    })
  } catch (e: any) {
    ElMessage.warning(e.message)
  }

  addConnect(list)
}
const addConnect = async (list: any) => {
  list.forEach((item: any) => {
    currentConnectInfo.connectFiled.push({
      title: item.title,
      sheet: item.sheet,
      row: item.row,
      colum: item.colum
    })

    currentConnectInfo.beConnectFiled.push({
      title: item.betitle,
      sheet: item.besheet,
      row: item.berow,
      colum: item.becolum
    })
  })
  currentConnectInfo.fileId = getFileInfo.value.orderFileId

  const { data } = await addExcelAreaConnect(currentConnectInfo)

  if (!data?.success) {
    ElMessage.error(data?.message || '操作失败！')
    return
  }
  ElMessage.success('添加成功！')
  connectVisible.value = false
  // 添加成功 手动更新页面数据
  connectList.value.push(data.result)
}
const chooseConnect = (row: any) => {
  currentConnectInfo.excelAreaId = row.excelAreaId
  Object.assign(cachCurrentConnectInfo, unref(row))
  chooseVisible.value = true
}
const connectConfigData = ref([])
const beConnectSelectOptions = computed(
  () =>
    areaList.value.find((v: any) => v.excelAreaId == currentConnectInfo.excelAreaBeId)
      ?.excelAreaTitle || []
)
watch(connectVisible, (val) => {
  if (val) {
    const titles = areaList.value.find((v: any) => v.excelAreaId == currentConnectInfo.excelAreaId)
      ?.excelAreaTitle

    connectConfigData.value = titles.map((item: any) => {
      return {
        title: item.title,
        sheet: item.sheet,
        row: item.row,
        colum: item.colum,
        betitle: '',
        berow: '',
        becolum: '',
        besheet: ''
      }
    })
  }
})
const changeBeConnect = (v: string, row: any) => {
  const option = beConnectSelectOptions.value.find((item: any) => item.title == v)
  console.log('option', option)
  row.becolum = option.colum
  row.besheet = option.sheet
  row.berow = option.row
  row.betitle = option.title
}
const confirmBeConnect = () => {
  const data = beConnectTable.value?.getRadioRecord()
  if (!data) {
    return ElMessage.warning('请选择有效数据！')
  }
  Object.assign(cachCurrentBeConnectInfo, unref(data))
  currentConnectInfo.excelAreaBeId = data.excelAreaId

  // 如果是公共区域，那么直接关联
  if (
    cachCurrentConnectInfo.excelAreaType == 'public_area' ||
    data.excelAreaType == 'public_area'
  ) {
    return addConnect([]).then(() => {
      chooseVisible.value = false
    })
  }

  // 打开关联弹窗。
  chooseVisible.value = false
  connectVisible.value = true
}
const chooseConnectOnHide = () => {
  Object.assign(currentConnectInfo, {
    // excelAreaConnectId: '',
    // excelAreaId: '',
    // excelAreaBeId: '',
    connectFiled: [],
    beConnectFiled: []
    // fileId: ''
  })
}
const delConnect = async (row: any, index: number) => {
  const { data } = await removeExcelAreaConnect(row.excelAreaConnectId)
  if (data?.success) {
    ElMessage.success('删除成功！')
  }
  // 手动删除
  connectList.value.splice(index, 1)
}
const queryConnectList = async () => {
  const { data } = await getExcelConnectByFileId(getFileInfo.value.orderFileId)
  connectList.value = data.result
}
const loadExcel = () => {
  LuckyExcel.transformExcelToLuckyByUrl(
    '/api/sys/static/' + getFileInfo.value.mergeFilePath,
    new Date().getTime() + '.xlsx',
    async (exportJson: any) => {
      console.log('---exportJson', exportJson)
      initIsSetSheetMark(exportJson.sheets.length)
      initExcelAreaMarksKey(exportJson.sheets.length)

      // 查询区域标记
      await queryArea()

      setSheetAuthority(exportJson)
      isFunction((window as any)?.luckysheet?.destroy) && luckysheet.destroy()
      luckysheet.create({
        container: 'luckysheet', //luckysheet is the container id
        showinfobar: false,
        showtoolbar: false,
        showsheetbar: false,
        showsheetbarConfig,
        cellRightClickConfig,
        sheetRightClickConfig,
        showstatisticBarConfig,
        data: exportJson.sheets,
        title: exportJson.info.name,
        userInfo: exportJson.info.name.creator,
        hook: {
          sheetActivate: (index: any) => {
            const sheet = luckysheet.getSheet({ index })
            nextTick(() => setSheetAreaMark(sheet))
          },
          workbookCreateAfter: () => {
            const sheet = luckysheet.getSheet()
            nextTick(() => setSheetAreaMark(sheet))
          }
        }
      })
    }
  )
}
const setSheetAreaMark = (sheet: any) => {
  if (!!isSetSheetMark.value[sheet.order]) {
    return
  }
  // 修改当前sheet 已经标记
  isSetSheetMark.value[sheet.order] = true
  // 判断本地是否记有第一个sheet页的标
  if (locaExcelAreaMarks[sheet.order].length) {
    locaExcelAreaMarks[sheet.order].forEach((item: any) => {
      // 设置数据区标记
      setRangeBackground(item, areaMarksColor['data'], false)
      // 设置数据区的标题
      if (item.excelAreaTitle.length) {
        const areas = JSON.parse(item.titleArea)
        areas?.forEach((area: any) => {
          luckysheet.menuButton.customUpdateFormat(
            null,
            'bg',
            areaMarksColor['head'],
            area.sr,
            area.er,
            area.sc,
            area.ec,
            false
          )
        })
      }
      // 设置附加信息
      if (item.desGroups.length) {
        item?.desGroups.forEach((area) => {
          if (area.beginRow !== null && area.beginRow !== '') {
            setRangeBackground(area, areaMarksColor['attch'], false)
          }
          // 设置附加信息的别称标题
          if (area.groupTitles.length) {
            area.groupTitles.forEach((a) => {
              setRangeBackground(a, areaMarksColor['attch_head'], false)
            })
          }
          // 设置附加信息的标题区
          if (area.areaTitles.length) {
            area.areaTitles.forEach((a) => {
              setRangeBackground(a, areaMarksColor['attch_title'], false)
            })
          }
        })
      }
      // 设置数据说明区
      item.dataTitles?.forEach((itm) => {
        setRangeBackground(itm, areaMarksColor['caption'], false)
      })
      // 设置排除区
      item.excludeTitles?.forEach((itm) => {
        setRangeBackground(itm, areaMarksColor['exclude'], false)
      })
    })
  }
}

const runResultData = ref<any[]>([])
const runResultTitle = ref<any[]>([])
const runResultVisible = ref(false)
const toRun = async () => {
  const loadingInstance = ElLoading.service({
    fullscreen: true,
    text: '解析中...'
  })
  try {
    const { data } = await excelMarkRun(getFileInfo.value.orderFileId)
    nextTick(() => {
      // Loading should be closed asynchronously
      loadingInstance.close()
    })
    if (data?.code != 200) {
      ElMessage.error(data?.message || '操作失败！')
      return
    }

    if (!data.result.length) return

    const { res, titles } = filterRunData(data.result)

    runResultData.value = res
    runResultTitle.value = titles.filter((field) => {
      return field != 'sortNum' && field != '数据区' && field != 'sheet页'
    })

    runResultVisible.value = true
  } catch {
    nextTick(() => {
      // Loading should be closed asynchronously
      loadingInstance.close()
    })
  }
}

const getCompareList = async () => {
  compareParams.customerId = getFileInfo.value.customerId || ''
  const { data } = await getExcelProdFileConfPage(compareParams)
  compareData.value = data.result.records
  compareParams.total = +data.result.total
}

const toDelete = async (row) => {
  const { data } = await deleteExcelProdFileConfByIds(row.excelProductFiledConfId)
  if (data.code === 200) {
    ElMessage.success('删除成功！')
    getCompareList()
  } else {
    ElMessage.error(data.message || '删除失败！')
  }
}

onMounted(() => {
  loadExcel()
  getCompareList()
  queryConnectList()
})
onUnmounted(() => {
  isFunction((window as any)?.luckysheet?.destroy) && luckysheet.destroy()
})
</script>
<style lang="scss" scoped>
.comment-form {
  .el-form-item--small {
    margin-bottom: 15px;
  }
}
</style>
<style lang="scss">
.current-area-mark {
  .el-descriptions__label {
    width: 8em;
  }
}
.expandTableHeader {
  background: #ccc;
}
</style>
