<template>
  <div class="list-table-v2" :style="containerStyle">
    <div class="my-table">
      <el-auto-resizer>
        <template #default="{ height, width }">
          <el-table-v2
            ref="table"
            :columns="tableColumns"
            :data="pageData"
            :width="width"
            :height="resolvedHeight(height)"
            :row-height="rowHeight"
            :header-height="headerHeight"
            :border="border"
            :row-key="rowKey"
            :class="border ? 'has-border' : ''"
            @scroll="onScroll"
            @row-click="onRowClick"
            @cell-click="onCellClick"
          />
        </template>
      </el-auto-resizer>
    </div>
    <div v-if="page" class="my-pagination">
      <el-pagination
        :small="state.size.size == 'small'"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="example.page"
        :page-sizes="[10, 20, 50, 100, 200]"
        :page-size="example.size"
        layout="total, sizes, prev, pager, next, jumper"
        :total="data.total"
      />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { useStore } from "vuex";
import { ref, computed, watch, h, onMounted, onUpdated, useSlots, renderSlot } from "vue";
import { useI18n } from "vue3-i18n";
import { ElAutoResizer, ElTableV2 } from "element-plus";
import * as lodash from "lodash-es";

const slots = useSlots();

const { t } = useI18n();
const { state } = useStore();
const table = ref();

// el-table-v2 uses fixed row heights for virtual scrolling by default
const ROW_HEIGHT = 50;
const HEADER_HEIGHT = 50;

interface TableColumn {
  code: string;
  name?: string;
  i18n?: string;
  type?: string;
  width?: string | number;
  minWidth?: string | number;
  fixed?: boolean | "left" | "right";
  align?: "left" | "center" | "right";
  slot?: boolean;
  dict?: string;
  timestamp?: boolean;
  filesize?: boolean;

  [others: string]: any;
}

interface Props {
  data?: any;
  columns?: TableColumn[];
  page?: boolean;
  height?: number | string;
  maxHeight?: number | string;
  example?: any;
  rowKey?: string;
  selectKey?: string;
  treeProps?: any;
  lazy?: boolean;
  border?: boolean;
}

const prop = withDefaults(defineProps<Props>(), {
  data: () => [],
  columns: () => [],
  page: false,
  height: undefined,
  maxHeight: undefined,
  example: () => ({}),
  rowKey: "id",
  selectKey: undefined,
  treeProps: undefined,
  lazy: false,
  border: false,
});

const emit = defineEmits(["query", "selection-change", "row-click", "cell-click"]);

const rowHeight = ROW_HEIGHT;
const headerHeight = HEADER_HEIGHT;

const containerStyle = computed(() => {
  const style: Record<string, string> = {};
  if (prop.height !== undefined) {
    style.height = typeof prop.height === "number" ? `${prop.height}px` : String(prop.height);
  } else {
    style.height = "100%";
  }
  if (prop.maxHeight !== undefined) {
    style.maxHeight = typeof prop.maxHeight === "number" ? `${prop.maxHeight}px` : String(prop.maxHeight);
  }
  return style;
});

// Use explicit height if provided, otherwise use auto from auto-resizer
const resolvedHeight = (autoHeight: number) => {
  if (prop.height !== undefined) {
    return typeof prop.height === "number" ? prop.height : parseInt(String(prop.height));
  }
  return autoHeight;
};

// Pagination data - use data.data if page response, otherwise data array
const pageData = computed(() => {
  if (!prop.data) return [];
  if (prop.page && prop.data.data) {
    return prop.data.data;
  }
  if (Array.isArray(prop.data)) {
    return prop.data;
  }
  return [];
});

const getValue = (value: any) => {
  if ((typeof value === "undefined" || value === null || value === "") && value !== 0) {
    return "--";
  }
  return value;
};

const formatStamp = (value: any) => {
  const date = new Date(value * 1000);
  const month = date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
  const day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
  const hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
  const minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
  const second = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
  return date.getFullYear() + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
};

const formatFileSize = (value: any) => {
  const k = value / 1024;
  if (k < 1) {
    return value + "B";
  }
  const m = k / 1024;
  if (m < 1) {
    return k.toFixed(2) + "K";
  }
  const g = m / 1024;
  if (g < 1) {
    return m.toFixed(2) + "M";
  }
  return g.toFixed(2) + "G";
};

const formatterByDist = (dictKey: string, value: any) => {
  if (!dictKey) {
    return getValue(value);
  }
  const mapping = state.dict[dictKey];
  if (mapping == null) {
    return getValue(value);
  }
  return mapping[value] == null ? value : mapping[value];
};

const formatCellValue = (value: any, item: TableColumn, row: any) => {
  if (item.dict) return formatterByDist(item.dict, value);
  if (item.timestamp) return formatStamp(value);
  if (item.filesize) return formatFileSize(value);
  if (row.scheme) return formatterByDist(row.scheme + "_" + item.code, value);
  return getValue(value);
};

const handleSizeChange = (val: number) => {
  prop.example.size = val;
  emit("query");
};

const handleCurrentChange = (val: number) => {
  prop.example.page = val;
  emit("query");
};

const onScroll = ({ scrollTop }: { scrollTop: number; scrollLeft?: number; horizontal?: boolean; vertical?: boolean }) => {
  // Can be used for lazy loading or other scroll-based features
};

const onRowClick = (row: any) => {
  emit("row-click", row);
};

const onCellClick = ({ row, column }: { row: any; column: any }) => {
  emit("cell-click", row, column, null, null);
};

// Build columns for el-table-v2
const tableColumns = computed(() => {
  return prop.columns.map((item: TableColumn) => {
    const col: any = {
      key: item.code,
      title: item.name || (item.i18n ? t(item.i18n) : item.code),
      dataKey: item.code,
      align: item.align || "center",
      fixed: item.fixed,
    };

    // If width is explicitly provided, use it; otherwise use flexGrow to auto-distribute
    if (item.width !== undefined) {
      col.width = typeof item.width === "number" ? item.width : parseInt(String(item.width)) || 120;
    } else {
      // Use flexGrow: 1 to auto-expand columns to fill available width
      col.flexGrow = 1;
      col.width = 120; // minimum width
    }

    if (item.minWidth !== undefined) {
      col.minWidth = typeof item.minWidth === "number" ? item.minWidth : parseInt(String(item.minWidth)) || 120;
    }

    // Cell renderer - el-table-v2 uses cellRenderer function, converts parent slots
    col.cellRenderer = ({ cellData, rowData }: { cellData: any; rowData: any }) => {
      const slotName = item.code;

      // If column has slot=true, render the parent's slot content
      if (item.slot && slots[slotName]) {
        return renderSlot(slots, slotName, { row: rowData });
      }

      const value = lodash.get(rowData, item.code);

      // Handle dict display
      if (item.dict) {
        return h("span", {}, formatterByDist(item.dict, value));
      }

      // Handle formatting
      const formatted = formatCellValue(value, item, rowData);
      return h("span", {}, formatted);
    };

    return col;
  });
});
</script>

<style lang="scss" scoped>
.list-table-v2 {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
}

.my-table {
  flex: 1;
  width: 100%;
  min-height: 0; // Important for flex child to shrink properly
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.my-table :deep(.el-table-v2) {
  --el-table-bg-color: v-bind("state.style.tableBg") !important;
  --el-table-tr-bg-color: v-bind("state.style.tableBg") !important;
  --el-table-expanded-cell-bg-color: v-bind("state.style.tableBg") !important;
  --el-table-border-color: v-bind("state.style.tableBorderColor");
  --el-table-text-color: v-bind("state.style.tableColor");
  --el-table-header-text-color: v-bind("state.style.tableColor");
  --el-table-row-hover-bg-color: v-bind("state.style.tableCurBg");
  --el-table-current-row-bg-color: v-bind("state.style.tableCurBg");
  --el-table-header-bg-color: v-bind("state.style.tableHeadBg");
  --el-bg-color: v-bind("state.style.tableBg") !important;
}

.my-table :deep(.el-table-v2__row) {
  background: v-bind("state.style.tableBg") !important;
}

.my-table :deep(.el-table-v2__row:hover) {
  background: v-bind("state.style.tableCurBg") !important;
}

.my-table :deep(.el-table-v2__cell) {
  padding: v-bind("state.size.tablePad");
}

.my-pagination {
  display: flex;
  justify-content: center;
  padding-top: 5px;
  flex-shrink: 0;
}

.my-pagination * {
  --el-pagination-bg-color: v-bind("state.style.bodyBg") !important;
  --el-pagination-disabled-bg-color: v-bind("state.style.bodyBg") !important;
  --el-pagination-text-color: v-bind("state.style.color") !important;
  --el-pagination-button-color: v-bind("state.style.color") !important;
  --el-pagination-button-disabled-bg-color: v-bind("state.style.bodyBg") !important;
}
</style>
