<template>
  <div class="drawer-data-table-wrap">
    <table class="data-table compact-table drawer-data-table">
      <colgroup>
        <col v-for="column in visibleColumns" :key="column.key" :style="{ width: column.width || 'auto' }" />
        <col v-if="expandable" style="width: 72px" />
      </colgroup>
      <thead>
        <tr>
          <th v-for="column in visibleColumns" :key="column.key" :title="headerTitle(column)">
            <span class="drawer-table-head-label">{{ headerLabel(column) }}</span>
          </th>
          <th v-if="expandable" title="详情">详情</th>
        </tr>
      </thead>
      <tbody>
        <template v-for="row in rows" :key="getRowKey(row)">
          <tr>
            <td v-for="column in visibleColumns" :key="column.key" :class="cellClass(column)">
              <slot :name="`cell-${column.key}`" :row="row" :column="column" :value="row[column.key]">
                <span :class="fallbackClass(column)" :title="formatFallback(row, column)">
                  {{ formatFallback(row, column) }}
                </span>
              </slot>
            </td>
            <td v-if="expandable" class="drawer-cell-actions">
              <button class="mini-icon-button" type="button" @click="toggleRow(row)">
                {{ isExpanded(row) ? "收起" : "展开" }}
              </button>
            </td>
          </tr>
          <tr v-if="expandable && isExpanded(row)" class="drawer-row-detail">
            <td :colspan="visibleColumns.length + 1">
              <slot name="detail" :row="row">
                <div class="drawer-row-detail-grid">
                  <article v-for="column in detailColumns" :key="column.key">
                    <span>{{ column.label }}</span>
                    <strong>{{ formatFallback(row, column) }}</strong>
                  </article>
                </div>
              </slot>
            </td>
          </tr>
        </template>
        <tr v-if="!rows.length">
          <td :colspan="visibleColumns.length + (expandable ? 1 : 0)" class="empty-row">{{ emptyText }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script setup>
import { computed } from "vue";

const props = defineProps({
  rows: {
    type: Array,
    default: () => []
  },
  columns: {
    type: Array,
    default: () => []
  },
  rowKey: {
    type: [String, Function],
    default: "id"
  },
  expandedRows: {
    type: Array,
    default: () => []
  },
  emptyText: {
    type: String,
    default: "暂无数据"
  }
});

const emit = defineEmits(["update:expandedRows"]);

const visibleColumns = computed(() => props.columns.filter((column) => !column.hidden && !column.detailOnly));
const detailColumns = computed(() => props.columns.filter((column) => column.detailOnly));
const expandable = computed(() => detailColumns.value.length > 0);

function getRowKey(row) {
  return typeof props.rowKey === "function" ? props.rowKey(row) : row?.[props.rowKey];
}

function isExpanded(row) {
  return props.expandedRows.includes(getRowKey(row));
}

function toggleRow(row) {
  const key = getRowKey(row);
  const nextRows = isExpanded(row) ? props.expandedRows.filter((item) => item !== key) : [...props.expandedRows, key];
  emit("update:expandedRows", nextRows);
}

function cellClass(column) {
  return {
    "drawer-cell-number": column.type === "number" || column.align === "right",
    "drawer-cell-status": column.type === "status",
    "drawer-cell-long": column.type === "code" || column.type === "longText"
  };
}

function fallbackClass(column) {
  return {
    "drawer-cell-code": column.type === "code",
    "drawer-cell-ellipsis": column.type === "longText" || column.type === "code"
  };
}

function headerLabel(column) {
  return column.compactLabel || column.label || column.title || column.key;
}

function headerTitle(column) {
  return column.title || column.label || column.compactLabel || column.key;
}

function formatFallback(row, column) {
  if (typeof column.format === "function") {
    return column.format(row[column.key], row);
  }
  const value = row?.[column.key];
  return value === null || value === undefined || value === "" ? "-" : String(value);
}
</script>
