<template>
  <div class="content-wrap">
    <el-row class="mb-10px">
      <!-- 动态按钮 -->
      <template v-for="btn in dynamicButtons">
        <el-button
          v-if="!btn.ifHide"
          :key="btn.id"
          type="primary"
          size="small"
          @click="handleDynamicButtonClick(btn)"
        >
          {{ btn.buttonName }}
        </el-button>
      </template>

      <el-button @click="AllConditionReset" size="small" type="danger">
        <i class="iconfont mr-5px">&#xe6a7;</i>
        全条件重置
      </el-button>
      <el-button @click="Export" size="small" type="primary">
        <i class="iconfont mr-5px">&#xe6a0;</i>
        导出
      </el-button>
      <el-button @click="ExportAll" :loading="exportLoading" size="small" type="success">
        <i class="iconfont mr-5px">&#xe6a0;</i>
        导出全部
      </el-button>
      <el-button @click="handleBack" size="small">
        <i class="iconfont mr-5px">&#xe6a9;</i>
        返回
      </el-button>
    </el-row>

    <el-table
      id="table_excel"
      v-loading="loading"
      :data="list"
      :stripe="true"
      :max-height="tableMaxHeight"
      :show-overflow-tooltip="true"
      size="small"
      :summary-method="getSummaries"
      @header-dragend="handleResize"
      show-summary
      border
      ref="tableRef"
      @selection-change="handleSelectionChange"
    >
      <el-table-column v-if="showMultipleList.length > 0" type="selection" width="55" />
      <el-table-column type="index" width="55" align="center" />
      <template v-for="(item, i) in queryData">
        <el-table-column
          v-if="item.ifHide === false"
          :key="i"
          :label="item.columnComment"
          align="center"
          :prop="item.columnComment"
          :show-overflow-tooltip="true"
          :min-width="item.javaField || ''"
          :sortable="false"
        >
          <template slot="header">
            <div class="mr-5px flex items-center">
              <div class="mr-5px flex flex-col gap-0" v-show="item.ifSort">
                <i
                  class="iconfont"
                  :class="{
                    'is-sort': currentSortField === item.columnComment && currentSortDirection === 'asc'
                  }"
                  style="font-size: 15px;"
                  @click="handleSort(item.columnComment, 'asc')"
                >&#xe6a3;</i>
                <i
                  class="iconfont -mt-1.2"
                  :class="{
                    'is-sort': currentSortField === item.columnComment && currentSortDirection === 'desc'
                  }"
                  style="font-size: 15px;"
                  @click="handleSort(item.columnComment, 'desc')"
                >&#xe6a4;</i>
              </div>
              <span>{{ item.columnComment }}</span>
              <filter-column-in-query
                v-if="item.listOperationResult"
                :label="item.columnComment"
                :prop="item.columnName"
                :filter-list="queryData"
                :query-id="$route.query.id"
                :filter-list-key="item.columnName"
                order-type="queryManage"
                :param-list="queryParamList"
                :active-filters="customFilters"
                :html-type="item.htmlType"
                @select-data="filterData"
                :dict-type="item.dictType"
                :is-clear="isClear"
              >
                <template slot="reference">
                  <div
                    class="flex items-center justify-center text-gray-600"
                    :class="{ 'has-filter': hasFilter(item.columnName) }"
                  >
                    <i class="iconfont ml-2px" style="font-size: 14px;">&#xe6a2;</i>
                  </div>
                </template>
              </filter-column-in-query>
            </div>
          </template>
          <template slot-scope="{ row }">
            <div
              @click="pathChange(item.example, row[item.columnComment], item, row)"
              :class="{ active: item.example }"
            >
              <dict-tag
                v-if="isDict(item.columnComment) && row[item.columnComment] !== undefined && row[item.columnComment] !== null"
                :type="isDict(item.columnComment)"
                :value="row[item.columnComment]"
              />
              <span v-else-if="row[item.columnComment] && isDateTime(item.columnComment)">
                {{ formatToDateTime(row[item.columnComment]) }}
              </span>
              <span v-else>{{ row[item.columnComment] }}</span>
            </div>
          </template>
        </el-table-column>
      </template>
    </el-table>

    <!-- 分页组件 -->
    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="pageNo"
      :limit.sync="pageSize"
      @pagination="handleSearch"
    />

    <!-- 积木标签打印 -->
    <!--<report-print ref="reportPrint" />--><!--暂时注掉-->
    <!-- 新增参数 -->
    <!--<parameter-detail ref="parameterDetailRef" @success="getQueryData" />--><!--暂时注掉-->
  </div>
</template>

<script>
  import * as QueryManageApi from '@/api/mes/queryManage'
  import { getQueryManageButtonPage } from '@/api/mes/queryManage/button'
  /*import download from '@/utils/download'
  import * as XLSX from 'xlsx'
  import { saveAs } from 'file-saver'
  import FilterColumnInQuery from './components/FilterColumnInQuery.vue'
  import ParameterDetail from './components/ParameterDetail.vue'
  import ReportPrint from '@/views/mes/personalManage/employeeMaster/components/ReportPrint.vue'
  import request from '@/config/axios'*/ //暂时注掉
  import { getAccessToken, getTenantId } from '@/utils/auth'
  import axios from 'axios'

  export default {
    name: 'QueryForm',
    /*components: {
      FilterColumnInQuery,
      ParameterDetail,
      ReportPrint
    },*/
    data() {
      return {
        title: '',
        queryList: [],
        searchData: [],
        queryData: [],
        list: [],
        originalList: [],
        pageNo: 1,
        pageSize: 20,
        total: 0,
        loading: false,
        form: {},
        visible: false,
        customFilters: {},
        currentSortField: null,
        currentSortDirection: null,
        dynamicButtons: [],
        queryParamList: [],
        exportLoading: false,
        showMultipleList: [],
        isClear: false,
        headerWidthChange: false,
        multipleSelection: []
      }
    },
    computed: {
      tableMaxHeight() {
        return 'calc(100vh - 230px)'
      }
    },
    methods: {
      hasFilter(field) {
        return !!this.customFilters[field] && this.customFilters[field].length > 0
      },

      async getQueryData() {
        try {
          this.loading = true
          const data = await QueryManageApi.getQueryManageColumnListByMasterId(this.$route.query.id)
          this.queryData = data

          this.searchData = data.filter((item) => {
            return item.listOperationResult && item.ifHide === false
          })
          this.showMultipleList = this.queryData.filter((item) => item.listOperationCondition === '1')
          this.queryList = []

          for (let i = 0; i < this.searchData.length; i++) {
            if (!this.searchData[i]) break
            const { dataType, htmlType, dictType, columnName } = this.searchData[i]
            this.queryList.push({
              dataType,
              htmlType,
              dictType,
              key: columnName,
              operate: dataType === 'ym_string_query_type' ? 'like' : ''
            })
          }

          await this.getManageButtons(this.$route.query.id)
          await this.getList()
        } catch (error) {
          console.error(error)
        } finally {
          this.loading = false
        }
      },

      async getList() {
        try {
          const data = await QueryManageApi.loadTableData({
            pageNo: this.pageNo,
            pageSize: this.pageSize,
            paramList: this.queryParamList,
            id: this.$route.query.id
          })
          this.list = data.list || []
          this.originalList = JSON.parse(JSON.stringify(data.list || []))
          this.total = data.total || 0
        } catch (error) {
          console.error(error)
        } finally {
          this.loading = false
        }
      },

      async getManageButtons(masterId) {
        try {
          const data = await getQueryManageButtonPage({ masterId })
          this.dynamicButtons = data.list || []
        } catch (error) {
          console.error(error)
        }
      },

      handleDynamicButtonClick(btn) {
        const { ifJimu, interfaceUrl, printSoft, operateType, paramList = [] } = btn
        if (ifJimu) {
          this.handlePrintByJimu(btn)
        } else if (this.isFullUrl(interfaceUrl) && printSoft) {
          this.handlePrintByOtherSoft(btn)
        } else if (operateType === 2) {
          this.$refs.parameterDetailRef.open('create', btn, this.$route.query.id, [], this.queryData)
        } else if (operateType === 3) {
          if (this.multipleSelection.length === 0) return this.$message.warning('请先选择行数据!')
          if (this.multipleSelection.length > 1) return this.$message.warning('只能选择单条数据修改!')
          this.$refs.parameterDetailRef.open(
            'update',
            btn,
            this.$route.query.id,
            this.multipleSelection,
            this.queryData
          )
        } else if (operateType === 7) {
          this.$router.push({ path: interfaceUrl })
        } else {
          this.handleDynamic(btn)
        }
      },

      handlePrintByJimu(params) {
        if (this.multipleSelection.length === 0) return this.$message.warning('请先选择数据!')
        const baseUrl = process.env.VUE_APP_BASE_URL
        const token = getAccessToken()
        const tenantId = getTenantId()
        const { paramList = [], interfaceUrl, reportId } = params
        const fieldValues = this.paramsToConver(paramList)
        const printParams = new URLSearchParams({
          token,
          tenantId,
          ...fieldValues
        })

        const src = `${baseUrl}${interfaceUrl}${reportId}?${printParams.toString()}`
        this.$refs.reportPrint.open(src, this.$route.query.name || '报表打印')
      },

      async handlePrintByOtherSoft(params) {
        if (this.multipleSelection.length === 0) return this.$message.warning('请先选择数据!')
        try {
          const { interfaceUrl, paramList, restMethod, templet } = params
          if (!templet) return this.$message.warning('未配置打印模板!')
          const fieldValues = this.paramsToConver(paramList)
          const printParams = {
            ...fieldValues,
            fileUrl: templet
          }

          const config = {
            method: restMethod,
            url: interfaceUrl
          }

          if (['post', 'put'].includes(restMethod)) {
            config.data = printParams
          } else {
            config.params = printParams
          }

          await axios(config)
          this.$message.success('操作成功!')
          this.getList()
        } catch (error) {
          console.error(error)
        }
      },

      async handleDynamic(params) {
        if (this.multipleSelection.length === 0) return this.$message.warning('请先选择数据!')
        const { interfaceUrl, restMethod = 'get', paramList = [], requestParameter = '0' } = params
        const fieldValues = this.paramsToConver(paramList)

        try {
          let config = { method: restMethod, url: interfaceUrl }

          if (restMethod === 'get' || restMethod === 'delete') {
            this.handleGetDelete(config, fieldValues, requestParameter)
          } else {
            if (requestParameter === '1') {
              this.handleGetDelete(config, fieldValues, requestParameter)
            } else {
              config.data = fieldValues
            }
          }

          await request[restMethod](config)
          this.$message.success('操作成功')
          this.getList()
        } catch (error) {
          console.error(error)
        }
      },

      handleGetDelete(config, fieldValues, requestParameter) {
        switch (requestParameter) {
          case '1':
            config.params = fieldValues
            break
          case '3':
            const queryString = new URLSearchParams(fieldValues).toString()
            config.url = queryString ? `${config.url}?${queryString}` : config.url
            break
          case '4':
            config.headers = { ...config.headers, ...fieldValues }
            break
          default:
            config.data = fieldValues
        }
      },

      generateMappedData(selectList, keys) {
        return selectList.map((item) =>
          keys.reduce((res, key) => {
            const { columnComment, paramName } = key
            if (item.hasOwnProperty(columnComment)) {
              const field = paramName.split('.').pop()
              res[field] = item[columnComment]
            }
            return res
          }, {})
        )
      },

      paramsToConver(paramList) {
        const matchListWithParam = (paramList || []).filter((item) =>
          this.queryData.some((query) => item.columnId === query.id)
        ).map((item) => {
          const paramItem = this.queryData.find((query) => item.columnId === query.id)
          return { ...item, columnComment: paramItem ? paramItem.columnComment : '' }
        })

        const result = this.generateMappedData(this.multipleSelection, matchListWithParam)
        const allFields = [...new Set(result.flatMap(Object.keys))]

        return allFields.reduce((acc, field) => {
          acc[field] = result.map((item) => item[field]).join(',')
          return acc
        }, {})
      },

      isFullUrl(url) {
        try {
          const parsed = new URL(url)
          return parsed.protocol === 'http:' || parsed.protocol === 'https:'
        } catch (e) {
          return false
        }
      },

      isDict(key) {
        const item = this.queryData.find((item) => item.columnComment === key)
        return item && item.dictType ? item.dictType : false
      },

      isNumber(key) {
        const item = this.queryData.find((item) => item.columnComment === key)
        return item && item.dataType === 'ym_int_query_type'
      },

      isDateTime(key) {
        const item = this.queryData.find((item) => item.columnComment === key)
        return item && item.javaType === 'LocalDateTime'
      },

      handleSort(field, direction) {
        if (this.currentSortField === field && this.currentSortDirection === direction) {
          this.currentSortField = null
          this.currentSortDirection = null
          this.list = [...this.originalList]
          return
        }

        this.currentSortField = field
        this.currentSortDirection = direction

        this.list = [...this.originalList].sort((a, b) => {
          let valA = a[field]
          let valB = b[field]

          valA = typeof valA === 'string' ? parseFloat(valA.replace(/,/g, '')) : valA
          valB = typeof valB === 'string' ? parseFloat(valB.replace(/,/g, '')) : valB

          if (isNaN(valA) || isNaN(valB)) {
            return direction === 'asc'
              ? String(valA).localeCompare(String(valB))
              : String(valB).localeCompare(String(valA))
          }

          return direction === 'asc' ? valA - valB : valB - valA
        })
      },

      filterData(data, field, type, item) {
        const { dataType } = item
        this.customFilters[field] = data

        if (data.length === 0) {
          const index = this.queryParamList.findIndex((item) => item.key === field)
          if (index > -1) this.queryParamList.splice(index, 1)
          this.getList()
          return
        }

        const isDateRange = data[0] && data[0].isRange
        let valueStr

        if (isDateRange) {
          valueStr = data.flatMap((item) => item.column).join(',')
        } else {
          valueStr = dataType === 'ym_int_query_type'
            ? data.map((item) => item.column).join(',')
            : data.map((item) => `'${item.column}'`).join(',')
        }

        const index = this.queryParamList.findIndex((item) => item.key === field)
        if (index > -1) {
          this.queryParamList[index].value = valueStr
        } else {
          this.queryParamList.push({ key: field, operate: 'like', htmlType: type, value: valueStr })
        }

        this.getList()
      },

      AllConditionReset() {
        this.queryParamList = []
        this.customFilters = {}
        this.isClear = true
        setTimeout(() => {
          this.isClear = false
          this.getList()
        }, 1000)
      },

      handleSearch() {
        this.getList()
      },

      async Export() {
        try {
          await this.$confirm('确定要导出数据吗？', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          })

          setTimeout(() => {
            const tables = document.getElementById('table_excel')
            const table_book = XLSX.utils.table_to_book(tables, { raw: true })
            const table_write = XLSX.write(table_book, {
              bookType: 'xlsx',
              bookSST: true,
              type: 'array'
            })
            saveAs(new Blob([table_write], { type: 'application/octet-stream' }), `${this.title}.xlsx`)
          }, 1000)
        } catch (error) {
          console.error(error)
        }
      },

      async ExportAll() {
        try {
          await this.$confirm('确定要导出全部数据吗？', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          })

          this.exportLoading = true
          const data = await QueryManageApi.exportExcel({
            id: this.$route.query.id,
            paramList: this.queryParamList
          })
          download.excel(data, this.title + '.xls')
        } catch (error) {
          console.error(error)
        } finally {
          this.exportLoading = false
        }
      },

      getHandleNumber(val) {
        return Math.round(parseFloat(val) * 100000000) / 100000000
      },

      getSummaries(param) {
        const { columns } = param
        const sums = []
        columns.forEach((column, index) => {
          if (index === 0) {
            sums[index] = '总计'
            return
          }

          if (this.isNumber(column.property)) {
            const values = this.list.map((item) => Number(item[column.property])).filter(val => !isNaN(val))
            sums[index] = values.reduce((acc, cur) => this.getHandleNumber(acc + cur), 0)
          } else {
            sums[index] = ''
          }
        })
        return sums
      },

      handleSelectionChange(val) {
        this.multipleSelection = val
      },

      pathChange(path, val, item, row) {
        if (!path || path === 'sameRouter') return

        const data = {}
        this.dynamicButtons.filter((v) => {
          if (v.ifHide && v.paramList) {
            v.paramList.forEach((param) => {
              data[param.paramName] = param.value || row[param.paramComment]
            })
          }
        })

        this.$router.push({ path, query: { id: val, ...data } })
      },

      handleResize() {
        this.headerWidthChange = true
      },

      handleBack() {
        this.$router.push({ path: '/querymanage/queryManageIndex' })
      },

      formatToDateTime(date) {
        if (!date) return ''
        try {
          const d = new Date(date)
          return d.toLocaleString()
        } catch (e) {
          return date
        }
      },

      async getFilterData() {
        const data = await getQueryManageButtonPage({ masterId: this.$route.query.infraQueryId })
        const arr = []

        data.list.forEach((v) => {
          if (v.ifHide && v.paramList) {
            v.paramList.forEach((val) => {
              if (val.filter) arr.push(val.paramName)
            })
          }
        })

        this.queryParamList = Object.keys(this.$route.query)
          .filter(key => key !== 'id' && key !== 'name' && arr.includes(key))
          .map(key => ({
            key,
            operate: 'like',
            htmlType: 'input',
            value: `'${this.$route.query[key]}'`
          }))

        await this.getQueryData()
      }
    },

    async mounted() {
      this.title = this.$route.query.name || ''
      if (this.$route.query.infraQueryId) {
        await this.getFilterData()
      } else {
        this.queryParamList = Object.keys(this.$route.query)
          .filter(key => key !== 'id' && key !== 'name')
          .map(key => ({
            key,
            operate: 'like',
            htmlType: 'input',
            value: `'${this.$route.query[key]}'`
          }))
        await this.getQueryData()
      }
    },

    activated() {
      if (this.$route.query.name) {
        this.title = this.$route.query.name
        if (this.$route.query.infraQueryId) {
          this.getFilterData()
        } else {
          this.queryParamList = Object.keys(this.$route.query)
            .filter(key => key !== 'id' && key !== 'name')
            .map(key => ({
              key,
              operate: 'like',
              htmlType: 'input',
              value: `'${this.$route.query[key]}'`
            }))
          this.getQueryData()
        }
      }
    },

    beforeDestroy() {
      if (!this.headerWidthChange) return

      const headers = this.$refs.tableRef.$el.querySelectorAll('.el-table__header-wrapper tr th')
      const visibleColumns = this.queryData.filter((item) => !item.ifHide)
      const widthList = []

      Array.from(headers).forEach((header, i) => {
        if (i >= visibleColumns.length) return
        if (header.classList.contains('el-table-column--selection')) return
        if (header.innerText.trim() === '') return

        widthList.push({
          id: visibleColumns[i].id,
          javaField: header.offsetWidth
        })
      })

      QueryManageApi.updateWidth(widthList).catch(console.error)
    }
  }
</script>

<style scoped>
  .mb-10px {
    margin-bottom: 10px;
  }

  .mr-5px {
    margin-right: 5px;
  }

  .ml-2px {
    margin-left: 2px;
  }

  .mt-1\.2 {
    margin-top: -1.2em;
  }

  .flex {
    display: flex;
  }

  .items-center {
    align-items: center;
  }

  .justify-center {
    justify-content: center;
  }

  .flex-col {
    flex-direction: column;
  }

  .gap-0 {
    gap: 0;
  }

  .text-gray-600 {
    color: #718096;
  }

  .active:hover {
    cursor: pointer;
    color: #1890ff;
  }

  .has-filter,
  .is-sort {
    color: #1890ff !important;
  }

  :deep(.el-table__row) {
    height: 15px !important;
  }

  :deep(.el-table--medium .el-table__cell),
  :deep(.el-table--small .el-table__cell) {
    padding: 1px 0 !important;
  }
</style>
