<template>
  <div
    v-if="isInit"
    class="low-reoprt"
    :class="[`low-report__${reportCode}`, { summary: tableOption.showSummary }]"
  >
    <avue-crud
      ref="crudRef"
      v-model:search="tableSearch"
      :table-loading="loading"
      :data="tableData"
      :option="tableOption"
      v-bind="crudBind"
      :summary-method=summaryMethod1
      @search-change="searchChange"
      @search-reset="resetChange"
      @refresh-change="refreshChange"
      @size-change="sizeChange"
      @current-change="currentChange"
      @selection-change="selectionChange"
      @sort-change="sortChange"
    >
      <!-- 自定义表格头部操作 -->
      <template #menu-left="{ size }">
        <ElButton
          type="primary"
          :size="size"
          :loading="exportLoading"
          @click="exportTableData"
          v-if="
            tableInfo.isHideExport !== true &&
            (!tableInfo.isPermi ||
              permissions === false ||
              (tableInfo.isPermi &&
                permissions.includes(`lideeyunji:report-data:export:${reportCode}`)))
          "
        >
          <Icon :size="14" icon="clarity:export-line"></Icon>
          <span>{{ t('Avue.crud.excelBtn') }}</span>
        </ElButton>
      </template>
      <template v-for="prop in numberRange" :key="prop" #[`${prop}-search`]="scope">
        <InputNumberRange
          v-model="tableSearch[prop]"
          :size="scope.size"
          :column="scope.column"
        ></InputNumberRange>
      </template>
      <template v-for="prop in dateRange" :key="prop" #[`${prop}-search`]="scope">
         <InputDateRange
          v-model="tableSearch[prop]"
          :size="scope.size"
          :column="scope.column"
        ></InputDateRange>
      </template>
      <template v-for="prop in dateTimeRange" :key="prop" #[`${prop}-search`]="scope">
         <InputDateTimeRange
          v-model="tableSearch[prop]"
          :size="scope.size"
          :column="scope.column"
        ></InputDateTimeRange>
      </template>
       <template v-for="prop in timeRange" :key="prop" #[`${prop}-search`]="scope">
         <InputTimeRange
          v-model="tableSearch[prop]"
          :size="scope.size"
          :column="scope.column"
        ></InputTimeRange>
      </template>
      <template #header v-if="Object.keys(dimensionFields)?.length">
        <div style="display:flex;margin-left:40px">
         <el-checkbox-group @change="searchDimension" v-model="tableSearch['Group by']"
                         placeholder="请选择内容">
            <template  v-for="(item,key) in dimensionFields">
              <el-checkbox  v-if="tableSearch['Group by']&&tableSearch['Group by'].includes(key)||!tableSearch['Group by']?.length"
                       :key="key"
                       :value="key"
                       :label="item.label"></el-checkbox>
                       </template>
              </el-checkbox-group>
            </div>
      </template>
    </avue-crud>
  </div>
  <div v-else class="h-200px" v-loading="!isInit"></div>
</template>
<script lang="ts" setup>
import * as ReportApi from '@/api/design/report'
import { InputNumberRange,InputDateRange ,InputDateTimeRange,InputTimeRange} from '../shareControl/index'
import download from '@/utils/download'
import { cloneDeep } from 'lodash-es'
import { useWindowSize } from '@vueuse/core'
import { assembleLengObj } from '@/utils/lowDesign'
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
import Avue from '@smallwei/avue'
defineOptions({ name: 'LowReport' })

interface Props {
  reportCode: string
  calcHeight?: number
  fixedSearch?: object //固定报表搜索值（每次查询都会带上）
}

const props = withDefaults(defineProps<Props>(), {
  model: 'default',
  fixedSearch: () => {
    return {}
  }
})
const windowSize = useWindowSize()
const { wsCache } = useCache()
const route = useRoute()
const message = useMessage() // 消息弹窗
const { mergeLocaleMessage, t } = useI18n() // 国际化

const loading = ref(false) // 列表的加载中
const isInit = ref(false)

const tableOption = ref<any>({})
const tableData = ref<any>([])
const tableSearch = ref({
  'Group by':[]
})
const tablePage = ref<any>({ currentPage: 1, pageSize: 100, total: 0 })
const tableSelect = ref<any>([])
const tableSort = ref({ column: '', order: '' })
const tableInfo = ref<any>({})
const timerObj = ref<any>({})
const numberRange = ref<string[]>([])
const dateRange=ref<string[]>([])
const hideColumns=ref<string[]>([])
const dateTimeRange=ref<string[]>([])
const timeRange=ref<string[]>([])
const amountFieds=ref<any>({})
const amountObj=ref<any>({})
const crudRef = ref()
const dimensionFields=ref<any>({})
const exportLoading = ref(false)
const fieldList = ref<any[]>([]) // 添加fieldList引用
const hideFeilds= ref<any>({}) 
const permissions =
  wsCache.get(CACHE_KEY.USER).lideeYunjipermissions?.[route.meta.menuDataId as string] || false
const selectIds = computed(() => {
  return tableSelect.value.map((item) => item['id'])
})
const crudBind = computed(() => {
  const obj = {}
  if (tableInfo.value.isPage) obj['page'] = tablePage.value
  return obj
})

const setLastAmountRowClass=(row,rowIndex)=>{
  if(row.isAmount===true){
    return 'lastAmountRow'
  }
}
const summaryMethod1=({columns,data})=>{
  // 1. 初始化汇总结果数组（和表格列数量一致）
      const result = new Array(columns.length).fill("");
      result[0] = `合计`;
      
      let keys=Object.values(amountFieds.value).map(item=>item.prop)
      columns.forEach((item,index)=>{
        if(keys.includes(item.property)){
          result[index]=amountObj.value[item.property]
        }
      })
      return result;
}
const initTable = async () => {
  isInit.value = false
  loading.value = true
  const { fieldList: apiFieldList, reportVo } = await ReportApi.getWebConfig(props.reportCode)
  
  // 存储字段列表到响应式引用
  fieldList.value = apiFieldList
  
  const isHeight = reportVo.tableConfig?.includes('height')
  const isPage = reportVo.dataConfig?.includes('page')
  const isPermi = reportVo.dataConfig?.includes('authTrue')
  const isHideExport = reportVo.tableConfig?.includes('hideExport')
  hideColumns.value=[]
  tableInfo.value = { ...reportVo, isPage, isHeight, isPermi, isHideExport }
  tableOption.value = {
    selection: !isHideExport,
    reserveSelection: true,
    menu: false,
    addBtn: false,
    height: isHeight ? 'auto' : undefined,
    calcHeight: isHeight ? 160 : '',
    index: reportVo.tableConfig.includes('index'),
    border: reportVo.tableConfig.includes('border'),
    stripe: reportVo.tableConfig.includes('stripe'),
    showSummary:false,
    
    column: {}
  }
  //国际化处理
  const fieldLengObj = assembleLengObj(apiFieldList, 'labelI18n', 'fieldCode', 'fieldName')
  for (const key in fieldLengObj) {
    mergeLocaleMessage(key, { [props.reportCode]: fieldLengObj[key] })
  }

  // 根据parentFieldCode判断表头结构
  const hasSubFields = Array.isArray(apiFieldList) && apiFieldList.some(field => field.parentFieldCode && field.parentFieldCode !== '')
  
  // 构建父子关系映射
  const parentChildMap = new Map()
  const childParentMap = new Map()
  
  // 建立映射关系
  apiFieldList.forEach(field => {
    if (field.parentFieldCode && field.parentFieldCode !== '') {
      // 这是子字段
      childParentMap.set(field.fieldCode, field.parentFieldCode)
      if (!parentChildMap.has(field.parentFieldCode)) {
        parentChildMap.set(field.parentFieldCode, [])
      }
      parentChildMap.get(field.parentFieldCode).push(field.fieldCode)
    }
  })
  
  //字段处理 - 构建正确的表头结构
  apiFieldList.forEach((item, index) => {
    // 跳过子字段，子字段会在父字段中处理
    if (item.parentFieldCode && item.parentFieldCode !== '') {
      return
    }
    
    const config: any = {
      prop: item.fieldCode,
      label: t(`${props.reportCode}.${item.fieldCode}`),
      type: 'input',
      overHidden: true,
      isExport: item.isExport == 'Y',
      sortable: item.isShowSort == 'Y' ? 'custom' : false,
      search: item.queryIsWeb == 'Y',
    }
    
    // 如果该字段有子字段，添加子列配置
    if (parentChildMap.has(item.fieldCode)) {
      const childFields = parentChildMap.get(item.fieldCode)
      config.children = childFields.map(childFieldCode => {
        const childField = apiFieldList.find(f => f.fieldCode === childFieldCode)
        return {
          prop: childField.fieldCode,
          label: t(`${props.reportCode}.${childField.fieldCode}`),
          type: 'input',
          overHidden: true,
          isExport: childField.isExport == 'Y',
          sortable: childField.isShowSort == 'Y' ? 'custom' : false,
          search: childField.queryIsWeb == 'Y'
        }
      })
    }
    
    if(!!item.isAmount){
      index==0?amountFieds.value.fistField=config.prop:''
      amountFieds.value[item.isAmount]=config
      tableOption.value.showSummary=true
    }
    if(item.isDimension=='Y'){
      dimensionFields.value[config.prop]=config
      hideFeilds.value[config.prop]=item.isHideDimension
    }
    if(item.isHideCol == 'Y')  {
      config.hide = true
      hideColumns.value.push( config.prop )
    }
    if (item.queryMode == 'RANGE') config.searchRange = true
    if (['Integer', 'BigInt', 'BigDecimal'].includes(item.fieldType)) config.type = 'number'
    else if (item.fieldType == 'Date') {
      config.type = 'date'
      config.format = 'YYYY-MM-DD'
      config.valueFormat = 'YYYY-MM-DD'
      if(config.searchRange){
        dateRange.value.push(config.prop)
      }
    } else if (item.fieldType == 'Time') {
      config.type = 'time'
      config.format = 'HH:mm:ss'
      config.valueFormat = 'HH:mm:ss'
      
      if(config.searchRange){
        timeRange.value.push(config.prop)
      }
    } else if (item.fieldType == 'DateTime') {
      config.type = 'datetime'
      config.format = 'YYYY-MM-DD HH:mm:ss'
      config.valueFormat = 'YYYY-MM-DD HH:mm:ss'
      if(config.searchRange){
        dateTimeRange.value.push(config.prop)
      }
    
    }
     
    if (config.type == 'number' && config.searchRange) numberRange.value.push(config.prop)
    if (item.queryMode == 'IN' && ['input', 'number'].includes(config.type)) {
      config.searchType = 'tag'
    }
    if (item.queryMode == 'NE') config.searchLabel = `${config.label} !=`
    tableOption.value.column[item.fieldCode] = config
  })

  
  isInit.value = true
  searchChange()
  initTableLayout()
}
const searchDimension=()=>{
  
  searchChange()
}
const initTableLayout = () => {
  if (tableOption.value.height != 'auto' && tableOption.value.height !== undefined) return

  if (tableInfo.value.isHeight || props.calcHeight) {
    const calcH = props.calcHeight
    let calcHeight = calcH || 160
    if (calcH) tableOption.value.height = 'auto'
    tableOption.value.calcHeight = calcHeight
  }

  if (timerObj.value.layout) clearTimeout(timerObj.value.layout)
  timerObj.value.layout = setTimeout(() => {
    if (crudRef.value) crudRef.value.getTableHeight()
  }, 100)
}

const selectionChange = (data) => {
  tableSelect.value = data
}
const clearSelection = () => {
  crudRef.value.clearSelection()
  tableSelect.value = []
}

const sortChange = ({ order, prop }) => {
  const sortKey = { ascending: 'asc', descending: 'desc' }
  tableSort.value = { order: sortKey[order], column: prop }
  if (tablePage.value) tablePage.value['currentPage'] = 1
  getTableData()
}
const getSearchData = () => {
  return new Promise(async (resolve) => {
    let searchObj: any = {}
    if (tableInfo.value.isPage) {
      const { currentPage, pageSize } = tablePage.value
      searchObj.pageNo = currentPage
      searchObj.pageSize = pageSize
    }
    for (let key in tableSearch.value) {
      if (tableSearch.value[key] instanceof Array) searchObj[key] = tableSearch.value[key].join(',')
      else searchObj[key] = tableSearch.value[key]
    }
    //排序
    if (tableSort.value.order) searchObj = { ...searchObj, ...tableSort.value }

    searchObj = { ...searchObj, ...props.fixedSearch }

    for (let key in searchObj) {
      if (searchObj[key] === '' || searchObj[key] == null) delete searchObj[key]
    }
    resolve(searchObj)
  })
}

const getTableData = async (isLoading = true) => {
  if (timerObj.value.getTableData) clearTimeout(timerObj.value.getTableData)
  await new Promise((resolve) => {
    timerObj.value.getTableData = setTimeout(() => resolve(true), 100)
  })
  return new Promise(async (resolve) => {
    if (isLoading) loading.value = true
    const searchObj = await getSearchData()
    try {
      const data = await ReportApi.getTableList(props.reportCode, searchObj)
      if (tablePage.value) tablePage.value['total'] = data.total
      
      // 处理包含子字段的数据
      let processedData = data.records
      // 根据字段配置判断是否需要处理子字段
      const hasSubFields = Array.isArray(fieldList.value) && fieldList.value.length > 0 && 
                          fieldList.value.some(field => field.parentFieldCode && field.parentFieldCode !== '')
      
      if (hasSubFields) {
        processedData = data.records.map(record => {
          const flatRecord = { ...record }
          // 处理子字段数据
          fieldList.value.forEach(field => {
            if (field.parentFieldCode && field.parentFieldCode !== '') {
              // 这是子字段，从父字段中提取数据
              const parentData = record[field.parentFieldCode]
              if (parentData && typeof parentData === 'object') {
                flatRecord[field.fieldCode] = parentData[field.fieldCode]
              }
            }
          })
          return flatRecord
        })
      }
      
      tableData.value = processedData
     // amountFieds.value={
      //  'thissaqty_s':{
       //   prop:'thissaqty',
       // },
       // "monthsaqty_s":{
       //   prop:'monthsaqty',
        //},
        //'lastsaqty_s':{
        //  prop:'lastsaqty'
        //}
      //}
      //tableData.value[0]['thissaqty_s']=6083195687
      // tableData.value[0]['monthsaqty_s']=972705058
      // tableData.value[0]['lastsaqty_s']=6075936725
      
      let keys=Object.keys(amountFieds.value)
      if(!!keys.length&&!!tableData.value.length){
        let obj={isAmount:true}
        keys.forEach(item=>{
          let key=amountFieds.value[item].prop
          key!=='fistField'?obj[key]=tableData.value[0][item]:''
        })
        amountObj.value=obj
      }
      resolve(data.records)
    } finally {
      if (isLoading) loading.value = false
    }
  })
}

const exportTableData = async () => {
  const isSelect = tableSelect.value.length
  await message.confirm(isSelect ? t('Avue.crud.exportTip') : t('Avue.crud.exportAllTip'))
  exportLoading.value = true
  if (isSelect) {
    const columnObj = cloneDeep(tableOption.value.column)
    const column: object[] = []
    for (let key in columnObj) {
      const { hide, isExport } = columnObj[key]
      if (!hide && isExport) column.push(columnObj[key])
    }
    let exportData = cloneDeep(tableSelect.value)
    exportData = exportData.map((item) => {
      for (let key in item) {
        if (key != '$index' && key.indexOf('$') === 0 && item[key]) {
          const prop = key.split('$')[1]
          item[prop] = item[key]
        }
      }
      return item
    })
    Avue.$Export.excel({ title: tableInfo.value.reportName, columns: column, data: exportData })
    exportLoading.value = false
  } else {
    const searchObj = await getSearchData()
    ReportApi.exportExcelData(props.reportCode, searchObj)
      .then((data) => download.excel(data, tableInfo.value.reportName))
      .finally(() => (exportLoading.value = false))
  }
}

/** 清空搜索值 */
const clearSearch = () => {
  try {
    crudRef.value?.searchReset()
  } catch (error) {
    resetChange()
  }
}

const searchChange = (params?, done?) => {
  if (tablePage.value) tablePage.value['currentPage'] = 1
  getTableData().finally(() => {
    let field=tableSearch.value['Group by']
    let hides=[]
    if(field.length){
      hides=Object.keys(hideFeilds.value).length?hideFeilds.value[field].split(','):[]
    }
    Object.keys(tableOption.value.column).forEach(key=>{
      let item=tableOption.value.column[key]
      item.hide=hides.includes(item.prop)||hideColumns.value.includes(item.prop)
    })
    if (done) done()
  })
}
const resetChange = () => {
  return new Promise(async (resolve) => {
    tableSearch.value = {}
    if (tablePage.value) tablePage.value['currentPage'] = 1
    await getTableData()
    resolve(true)
  })
}
const sizeChange = (pageSize) => {
  if (tablePage.value) tablePage.value['pageSize'] = pageSize
  clearSearch()
}
const currentChange = (currentPage) => {
  if (tablePage.value) tablePage.value['currentPage'] = currentPage
  getTableData()
}
const refreshChange = () => {
  getTableData()
}

watch(
  () => props.reportCode,
  (value: string) => {
    if (value) initTable()
  },
  { immediate: true }
)

watch(
  [() => windowSize.height.value, () => props.calcHeight],
  () => {
    initTableLayout()
  },
  { immediate: true }
)

onUnmounted(() => {
  for (let key in timerObj.value) {
    clearInterval(timerObj.value[key])
    clearTimeout(timerObj.value[key])
  }
})

defineExpose({
  crudRef,
  tableSelect,
  selectIds,
  loading,
  clearSelection,
  resetChange:clearSearch,
  initTableLayout
})
</script>

<style lang="scss" scoped>
  .amountBox{
    &::after{
      content:'、'
    }
    &:last-of-type::after{
      content:''
    }
  }
  .lastAmountRow{

  }
</style>
