<template>
  <div class="generic-monitor-list">
    <el-card shadow="never">
      <el-form :inline="true" :model="filters" class="filter-form">
        <el-form-item v-for="col in filterableColumns" :key="col.dataIndex" :label="col.title">
          <template v-if="col.filterType === 'text'">
            <el-input
              v-model="filters[col.dataIndex]"
              :placeholder="`搜索 ${col.title}`"
              clearable
              @change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
            ></el-input>
          </template>
          <template v-else-if="col.filterType === 'number'">
            <el-input-number
              v-model="filters[col.dataIndex]"
              :placeholder="`搜索 ${col.title}`"
              :controls="false"
              clearable
              @change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
            ></el-input-number>
          </template>
          <template v-else-if="col.filterType === 'dateRange'">
            <el-date-picker
              v-model="filters[col.dataIndex]"
              type="datetimerange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="YYYY-MM-DD HH:mm:ss"
              @change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
            ></el-date-picker>
          </template>
          <template v-else-if="col.filterType === 'select'">
            <el-select
              v-model="filters[col.dataIndex]"
              :placeholder="`选择 ${col.title}`"
              clearable
              @change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
            >
              <el-option
                v-for="option in col.filterOptions"
                :key="option.value"
                :label="option.text"
                :value="option.value"
              ></el-option>
            </el-select>
          </template>
          <template v-else-if="col.filterType === 'boolean'">
            <el-select
              v-model="filters[col.dataIndex]"
              :placeholder="`选择 ${col.title}`"
              clearable
              @change="handleFilterChange(col.dataIndex, filters[col.dataIndex])"
            >
              <el-option label="是" :value="true"></el-option>
              <el-option label="否" :value="false"></el-option>
            </el-select>
          </template>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="loadData">查询</el-button>
          <el-button @click="resetFilters">重置</el-button>
        </el-form-item>
      </el-form>

      <el-table
        :data="data"
        v-loading="loading"
        border
        style="width: 100%"
        @sort-change="handleSortChange"
      >
        <el-table-column
          v-for="col in tableColumns"
          :key="col.key"
          :prop="col.prop"
          :label="col.title"
          :sortable="col.sorter ? 'custom' : false"
          :formatter="col.formatter"
        >
          <template v-if="col.render" #default="{ row }">
            <component :is="col.render(row)" />
          </template>
        </el-table-column>
      </el-table>

      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="pagination.currentPage"
        :page-sizes="[10, 20, 50, 100]"
        :page-size="pagination.pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pagination.total"
        background
        style="margin-top: 20px; text-align: right;"
      ></el-pagination>
    </el-card>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, watch, computed } from 'vue';
import { ElMessage } from 'element-plus';

const props = defineProps({
  fetchData: {
    type: Function,
    required: true,
  },
  columnsConfig: {
    type: Array,
    required: true,
  },
});

const data = ref([]);
const loading = ref(false);
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
});
const filters = reactive({});
const sortOrder = reactive({
  prop: undefined,
  order: undefined,
});

const filterableColumns = computed(() => {
  return props.columnsConfig.filter(col => col.filterType);
});

const tableColumns = computed(() => {
  return props.columnsConfig.map(col => {
    const newCol = { ...col };
    newCol.prop = Array.isArray(col.dataIndex) ? col.dataIndex.join('.') : col.dataIndex;
    return newCol;
  });
});

const loadData = async () => {
  loading.value = true;
  try {
    const params = {
      page: pagination.currentPage,
      pageSize: pagination.pageSize,
      ...filters,
      orderBy: sortOrder.prop,
      order: sortOrder.order === 'ascending' ? 'asc' : (sortOrder.order === 'descending' ? 'desc' : undefined),
    };

    // 将日期范围筛选转换为 start_time 和 end_time
    filterableColumns.value.forEach(col => {
      if (col.filterType === 'dateRange' && filters[col.dataIndex] && filters[col.dataIndex].length === 2) {
        params[`start_time`] = filters[col.dataIndex][0];
        params[`end_time`] = filters[col.dataIndex][1];
        delete params[col.dataIndex];
      }
    });

    const result = await props.fetchData(params);
    data.value = result.list;
    pagination.total = result.total;
  } catch (error) {
    console.error('Failed to fetch data:', error);
    ElMessage.error('获取数据失败，请稍后再试。');
  } finally {
    loading.value = false;
  }
};

const handleSizeChange = (val) => {
  pagination.pageSize = val;
  pagination.currentPage = 1;
  loadData();
};

const handleCurrentChange = (val) => {
  pagination.currentPage = val;
  loadData();
};

const handleSortChange = ({ prop, order }) => {
  sortOrder.prop = prop;
  sortOrder.order = order;
  loadData();
};

const handleFilterChange = (key, value) => {
  filters[key] = value;
  pagination.currentPage = 1;
};

const resetFilters = () => {
  for (const key in filters) {
    delete filters[key];
  }
  sortOrder.prop = undefined;
  sortOrder.order = undefined;
  pagination.currentPage = 1;
  loadData();
};

onMounted(() => {
  loadData();
});

</script>

<style scoped>
.generic-monitor-list {
  padding: 20px;
}
.filter-form {
  margin-bottom: 20px;
}
.el-card {
    border: none;
}
</style>
