<script setup lang="ts">
import { ref, provide, onMounted } from 'vue'
import { post, get } from "@/utils/request";
import { GET_RES_BY_FORM_JSON } from '../api';
import type { TableColumnCtx, SummaryMethod  } from 'element-plus'

import rangeFilter from "./rangeFilter.vue";
import { rangeGetSql } from '../function';
import { formatDate } from '@/utils/times';

const rangeFilterRef = ref<InstanceType<typeof rangeFilter> | null>(null);

const SQLstr = ref<string>('')
const driginalDataTableList = ref<any[]>([])
const addEditData = JSON.parse(sessionStorage.getItem('reportJson') || '{}')
const tableHeader = ref<any[]>([])
const tableData = ref<any[]>([])
const tableLoading = ref(false)
const dataRangeData = ref<any[]>([])
const dataRangeDataVisable = ref(false)
const listThatNeedsToBeGrouped = ref<number[]>([]) // 分组索引
const listStatisticsList = ref<number[]>([]) // 统计索引
const tableKey = ref<number>(1)

// 统计
const getSummaries: SummaryMethod<any> = (params) => {
  const { columns, data } = params
  const sums: (string)[] = []

  columns.forEach((column, index) => {
    if (index === 0) {
      sums[index] = '合计'
      return
    }
    const values = data.map(item => Number(item[column.property as string]))
    if (!values.every(value => isNaN(value)) && listStatisticsList.value.includes(index)) {
      const total = values.reduce((prev, curr) => {
        const value = Number(curr)
        if (!isNaN(value)) {
          return prev + curr
        } else {
          return prev
        }
      }, 0)
      sums[index] = total.toFixed(2) // 保证返回 string，解决类型报错
    } else {
      sums[index] = ''
    }
  })

  return sums
}

// 合并分组
function mergeColumns({ row, rowIndex, columnIndex }: { row: any, rowIndex: number, columnIndex: number }) {
  // 只处理需要合并的列
  if (!listThatNeedsToBeGrouped.value.includes(columnIndex)) {
    return { rowspan: 1, colspan: 1 };
  }

  const field = tableHeader.value[columnIndex]?.label;
  if (!field) return { rowspan: 1, colspan: 1 };

  // 当前行之前的内容已经合并过，直接跳过
  if (rowIndex > 0 && tableData.value[rowIndex - 1][field] === row[field]) {
    return { rowspan: 0, colspan: 0 }; // 隐藏
  }

  // 计算当前单元格应该合并多少行
  let rowspan = 1;
  for (let i = rowIndex + 1; i < tableData.value.length; i++) {
    if (tableData.value[i][field] === row[field]) {
      rowspan++;
    } else {
      break;
    }
  }

  return { rowspan, colspan: 1 };
}

function determinationOfDataRange() {
  const rangeFilterData = rangeFilterRef.value?.getRangeData()
  const rangeSQL = rangeGetSql(rangeFilterData, addEditData)
  const sqlList = SQLstr.value.split('where')[0]
  SQLstr.value = `${sqlList}${rangeSQL}`
  dataRangeDataVisable.value = false
  getData()
}

function setDataRange() {
  dataRangeDataVisable.value = true
  setTimeout(() => {
    rangeFilterRef.value?.setRangeData(dataRangeData.value)
  }, 100)
}

function getData() {
  tableLoading.value = true
  post(GET_RES_BY_FORM_JSON, { formJson: SQLstr.value }).then(res => {
    tableData.value = res.data
    setTimeout(() => {
      tableKey.value++
    }, 100)
  }).finally(() => {
    tableLoading.value = false
  })
} 

async function initializedData(SQL: string, rangeFilterList: any[], tableData: any[]) {
  await filterGroupStatistics(tableData)
  
  const heading = tableData.map(item => ({
    filed: `${item.tableName}_${item.columnName}`,
    label: item.columnComment,
    type: item.dataType,
  }))
  
  driginalDataTableList.value = tableData
  tableHeader.value = heading
  dataRangeData.value = rangeFilterList
  SQLstr.value = SQL

  console.log(tableHeader.value, '<==== tableHeader.value')
  getData()
}

// 过滤出需要分组和统计的数组
function filterGroupStatistics(tableData: any[]) {
  return new Promise<void>((resolve) => {
    const numberList = tableData.map((item: any, index: number) => item?.singleColumnOperation?.grouping ? index : 9999)
    const statisticsList = tableData.map((item: any, index: number) => item?.singleColumnOperation?.statistics ? index : 9999)
    listThatNeedsToBeGrouped.value = numberList.filter((item: any) => item != 9999)
    listStatisticsList.value = statisticsList.filter((item: any) => item != 9999)
    resolve()
  })
}

defineExpose({
  initializedData
});

onMounted(() => { })
</script>

<template>
  <div class="h-full flex flex-col">
    <div class="flex items-center mb-4 h-[5%]">
      <el-button type="primary" @click="setDataRange()">设置数据范围</el-button>
    </div>
    <div class="flex-1 h-[92%]">
      <el-table :data="tableData" border style="width: 100%;height: 100%" v-loading="tableLoading" :span-method="mergeColumns" :summary-method="getSummaries" :show-summary="listStatisticsList.length > 0 ? true : false" :key="tableKey">
        <el-table-column :prop="item.label" :label="item.label" min-width="240" v-for="(item, index) in tableHeader">
          <template #default="scope">
            <template v-if="item.type == 'timestamp' || item.type == 'datetime' || item.type == 'timestamp' || item.type == 'date'">
              {{ scope.row[item.label] ? formatDate(new Date(scope.row[item.label])) : '' }}
            </template>
            <template v-else>
              {{ scope.row[item.label] }}
            </template>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- 数据范围弹框 -->
    <el-dialog v-model="dataRangeDataVisable" width="680" :show-close="false" top="10vh">
      <template #header="{ close, titleId, titleClass }">
        <div class="flex justify-between items-center border-b pb-3 dialog-header">
          <h4 :id="titleId">数据范围</h4>
          <div class="flex">
            <el-button @click="dataRangeDataVisable = false">取消</el-button>
            <el-button type="primary" @click="determinationOfDataRange()">确定</el-button>
          </div>
        </div>
      </template>
      <div class="p-8">
        <rangeFilter ref="rangeFilterRef" />
      </div>
    </el-dialog>
  </div>
</template>

<style lang="scss"></style>
