<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import type { DatasetRecord } from '../datasetRecords'

const props = defineProps<{
  records: DatasetRecord[]
  isViewingActiveVersion: boolean
  versionId: string
}>()

const emit = defineEmits<{
  edit: [record: DatasetRecord]
}>()

const pageSize = 10
const searchText = ref('')
const currentPage = ref(1)

const allTableFieldKeys = computed(() => {
  const keys = new Set<string>()
  props.records.forEach((record) => {
    if (record.kind !== 'object') return
    Object.keys(record.value as Record<string, unknown>).forEach((key) => keys.add(key))
  })
  const preferred = ['instruction', 'question', 'prompt', 'input', 'context', 'output', 'answer', 'response']
  return [...keys].sort((a, b) => {
    const rank = (key: string) => {
      const index = preferred.indexOf(key)
      return index === -1 ? preferred.length : index
    }
    return rank(a) - rank(b)
  })
})
const tableFieldKeys = computed(() => allTableFieldKeys.value.slice(0, 6))
const invalidRecordCount = computed(() => props.records.filter((record) => record.kind === 'invalid').length)
const hasExtraTableFields = computed(() => allTableFieldKeys.value.length > tableFieldKeys.value.length)
const filteredRecords = computed(() => {
  const query = searchText.value.trim().toLowerCase()
  if (!query) return props.records
  return props.records.filter((record) => JSON.stringify(record.value).toLowerCase().includes(query))
})
const pagedRecords = computed(() => {
  const start = (currentPage.value - 1) * pageSize
  return filteredRecords.value.slice(start, start + pageSize)
})

watch(
  () => props.versionId,
  () => {
    searchText.value = ''
    currentPage.value = 1
  },
)

function asDatasetRecord(row: unknown) {
  return row as DatasetRecord
}

function formatFieldValue(value: unknown) {
  if (typeof value === 'string') return value || '（空）'
  return JSON.stringify(value)
}

function recordFieldValue(record: DatasetRecord, key: string) {
  if (record.kind !== 'object') {
    return record.kind === 'invalid' ? record.raw : formatFieldValue(record.value)
  }
  const data = record.value as Record<string, unknown>
  return Object.prototype.hasOwnProperty.call(data, key) ? formatFieldValue(data[key]) : '-'
}

function extraFieldValue(record: DatasetRecord) {
  if (record.kind !== 'object') return '-'
  const data = record.value as Record<string, unknown>
  return allTableFieldKeys.value
    .filter((key) => !tableFieldKeys.value.includes(key) && Object.prototype.hasOwnProperty.call(data, key))
    .map((key) => `${key}: ${formatFieldValue(data[key])}`)
    .join('；') || '-'
}

function recordRowClassName({ row }: { row: unknown }) {
  return asDatasetRecord(row).kind === 'invalid' ? 'record-table-row-invalid' : ''
}
</script>

<template>
  <div class="records-viewer">
    <div class="records-toolbar">
      <div>
        <strong>样本数据</strong>
        <span>共 {{ records.length.toLocaleString() }} 条</span>
        <el-tag v-if="invalidRecordCount" size="small" type="danger">
          {{ invalidRecordCount }} 条格式错误
        </el-tag>
      </div>
      <el-input
        v-model="searchText"
        class="record-search"
        clearable
        placeholder="搜索样本内容"
        aria-label="搜索样本内容"
        @input="currentPage = 1"
      >
        <template #prefix><i class="fa fa-search" /></template>
      </el-input>
    </div>

    <div v-if="!filteredRecords.length" class="viewer-state record-empty-state">
      <i class="fa fa-search" aria-hidden="true" />
      <span>没有找到匹配的样本</span>
    </div>
    <div v-else class="record-table-shell" aria-label="数据样本表格">
      <el-table
        :data="pagedRecords"
        row-key="sourceIndex"
        stripe
        border
        class="record-table"
        :row-class-name="recordRowClassName"
      >
        <el-table-column label="序号" width="76" align="center">
          <template #default="{ row }">
            <div class="table-index">
              <strong>{{ asDatasetRecord(row).displayIndex }}</strong>
              <small>第 {{ asDatasetRecord(row).sourceIndex + 1 }} 行</small>
            </div>
          </template>
        </el-table-column>
        <el-table-column
          v-for="fieldKey in tableFieldKeys"
          :key="fieldKey"
          :label="fieldKey"
          min-width="220"
        >
          <template #default="{ row }">
            <el-tooltip
              :content="recordFieldValue(asDatasetRecord(row), fieldKey)"
              placement="top"
              :show-after="400"
            >
              <div class="table-cell-text">
                {{ recordFieldValue(asDatasetRecord(row), fieldKey) }}
              </div>
            </el-tooltip>
          </template>
        </el-table-column>
        <el-table-column v-if="hasExtraTableFields" label="其他字段" min-width="240">
          <template #default="{ row }">
            <el-tooltip
              :content="extraFieldValue(asDatasetRecord(row))"
              placement="top"
              :show-after="400"
            >
              <div class="table-cell-text">{{ extraFieldValue(asDatasetRecord(row)) }}</div>
            </el-tooltip>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="96" align="center">
          <template #default="{ row }">
            <el-tag v-if="asDatasetRecord(row).kind === 'invalid'" size="small" type="danger">
              格式错误
            </el-tag>
            <el-tag v-else-if="asDatasetRecord(row).kind === 'primitive'" size="small" type="warning">
              非对象
            </el-tag>
            <el-tag v-else size="small" type="success">正常</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="96" align="center" fixed="right">
          <template #default="{ row }">
            <el-button
              type="primary"
              link
              :disabled="!isViewingActiveVersion"
              :title="isViewingActiveVersion ? '' : '历史版本为只读，请先设为当前版本'"
              :aria-label="`${asDatasetRecord(row).kind === 'invalid' ? '修复' : '编辑'}第 ${asDatasetRecord(row).displayIndex} 条数据`"
              @click="emit('edit', asDatasetRecord(row))"
            >
              <i :class="asDatasetRecord(row).kind === 'invalid' ? 'fa fa-wrench' : 'fa fa-pencil'" />
              {{ asDatasetRecord(row).kind === 'invalid' ? '修复' : '编辑' }}
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div v-if="filteredRecords.length > pageSize" class="records-pagination">
      <el-pagination
        v-model:current-page="currentPage"
        :page-size="pageSize"
        :total="filteredRecords.length"
        layout="prev, pager, next"
        background
      />
    </div>
  </div>
</template>

<style scoped lang="scss">
.records-viewer {
  min-height: 468px;
  padding: 16px;
  box-sizing: border-box;
}

.records-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}

.records-toolbar > div {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.records-toolbar strong {
  color: #253047;
  font-size: 14px;
}

.records-toolbar span {
  color: #8a94a6;
  font-size: 12px;
}

.record-search {
  width: 240px;
}

.record-table-shell {
  overflow: hidden;
  border: 1px solid #e4e9f1;
  border-radius: 8px;
}

.record-table {
  width: 100%;
}

.record-table :deep(.el-table__header th) {
  height: 44px;
  background: #f5f7fa;
  color: #475467;
  font-size: 12px;
  font-weight: 600;
}

.record-table :deep(.el-table__cell) {
  padding: 10px 0;
}

.record-table :deep(.record-table-row-invalid td) {
  background: #fff7f7 !important;
}

.table-index {
  display: flex;
  align-items: center;
  flex-direction: column;
  gap: 1px;
  color: #667085;
  font-variant-numeric: tabular-nums;
}

.table-index strong {
  font-size: 13px;
  font-weight: 600;
}

.table-index small {
  color: #98a2b3;
  font-size: 10px;
}

.table-cell-text {
  display: -webkit-box;
  overflow: hidden;
  color: #526076;
  font-size: 12px;
  line-height: 1.6;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.record-table .el-button i {
  margin-right: 5px;
}

.records-pagination {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}

.viewer-state {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  min-height: 400px;
  color: #8b96a8;
  font-size: 13px;
}

.viewer-state > i {
  color: #aeb7c5;
  font-size: 24px;
}

.record-empty-state {
  min-height: 320px;
}

@media (max-width: 680px) {
  .records-toolbar {
    align-items: stretch;
    flex-direction: column;
  }

  .record-search {
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .record-table :deep(.el-table__row) { transition: none; }
}
</style>
