<!--
  功能：以响应式信息卡和子表页签展示标准资源详情。
  版本：v1.3.0
-->
<template>
  <div class="detail-stack">
    <a-card title="基本信息" :bordered="false" class="detail-card">
      <div class="detail-grid">
        <div v-for="entry in entries" :key="entry.key" class="detail-item" :class="{ 'detail-item-wide': entry.wide }">
          <span class="detail-label">{{ entry.label }}</span>
          <pre v-if="entry.objectValue" class="json-value">{{ entry.value }}</pre>
          <IdentityText v-else-if="entry.key === 'identity'" :value="String(entry.value)" />
          <div v-else-if="entry.identityValue" class="detail-relation-value">
            <span class="detail-value">{{ entry.value }}</span>
            <IdentityText :value="entry.identityValue" />
          </div>
          <span v-else class="detail-value">{{ entry.value }}</span>
        </div>
      </div>
    </a-card>

    <a-card v-if="collections.length" title="关联记录" :bordered="false" class="detail-card">
      <a-tabs>
        <a-tab-pane v-for="collection in collections" :key="collection.key" :title="collection.title">
          <a-table :data="collection.rows" :pagination="false" size="small" table-layout-fixed>
            <template #columns>
              <a-table-column
                v-for="column in collection.columns"
                :key="column"
                :title="resourceFieldLabel(definition, column, collection.key)"
                :width="column.includes('identity') ? 220 : 160"
                ellipsis
                tooltip
              >
                <template #cell="{ record }">
                  <IdentityText v-if="column.includes('identity') && record[column]" :value="String(record[column])" />
                  <template v-else>{{ displayRawValue(column, record[column]) }}</template>
                </template>
              </a-table-column>
            </template>
          </a-table>
        </a-tab-pane>
      </a-tabs>
    </a-card>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import IdentityText from '@/components/IdentityText.vue';
import {
  displayRawValue,
  displayResourceField,
  isEmptyDeletedAt,
  primaryRecord,
  resourceFieldLabel,
} from '@/api/resource-display';
import type { ResourceUiDefinition } from '@/api/resources';
import type { ResourceRow } from '@/api/resource-page-rules';

const props = defineProps<{
  definition: ResourceUiDefinition;
  detail: ResourceRow;
  relationOptions: Record<string, ResourceRow[]>;
  fieldOptions?: Record<
    string,
    Array<{ label: string; value: string | number }>
  >;
  accountSummary: boolean;
}>();

type DetailEntry = {
  key: string;
  label: string;
  value: string;
  objectValue: boolean;
  wide: boolean;
  identityValue: string;
};

const entries = computed<DetailEntry[]>(() => {
  const row = primaryRecord(props.detail);
  const excluded = new Set(['id', 'password', 'password_hash', 'avatar']);
  if (props.accountSummary) {
    for (const key of ['username', 'identity', 'created_at']) excluded.add(key);
  }
  const preferred = [
    'identity',
    'status',
    ...props.definition.fields.map((field) => field.key),
    'created_at',
    'updated_at',
  ];
  const keys = [...new Set([...preferred, ...Object.keys(row)])];
  return keys.flatMap((key) => {
    const maskedKey = `${key}_masked`;
    const actualKey = Object.prototype.hasOwnProperty.call(row, key)
      ? key
      : Object.prototype.hasOwnProperty.call(row, maskedKey)
        ? maskedKey
        : '';
    if (!actualKey || excluded.has(key) || key.endsWith('_id')) return [];
    const value = row[actualKey];
    if (Array.isArray(value)) return [];
    if (['deleted_at', 'DeletedAt'].includes(key) && isEmptyDeletedAt(value))
      return [];
    const field = props.definition.fields.find((item) => item.key === key);
    const display = field
      ? displayResourceField(
          field,
          row,
          props.relationOptions,
          props.fieldOptions,
        )
      : displayRawValue(actualKey, value);
    const objectValue = typeof value === 'object' && value !== null;
    return [
      {
        key,
        label: resourceFieldLabel(props.definition, actualKey),
        value: display,
        objectValue,
        identityValue:
          (field?.showIdentityCopy || field?.staffRelation?.showIdentityCopy) && value
            ? String(value)
            : '',
        wide:
          objectValue ||
          /(address|terms|content|body|remark|reason|params|args)$/.test(key),
      },
    ];
  });
});

const collections = computed(() =>
  Object.entries(props.detail)
    .filter(([, value]) => Array.isArray(value) && value.length > 0)
    .map(([key, value]) => {
      const rows = value as ResourceRow[];
      const columns = [
        ...new Set(
          rows.flatMap((row) =>
            Object.keys(row).filter(
              (column) => column !== 'id' && !column.endsWith('_id'),
            ),
          ),
        ),
      ].slice(0, 8);
      return {
        key,
        title: resourceFieldLabel(props.definition, key),
        rows,
        columns,
      };
    }),
);
</script>

<style scoped lang="less">
.detail-stack {
  display: grid;
  gap: 12px;
}
.detail-card {
  border-radius: 10px;
}
.detail-card :deep(.arco-card-header) {
  height: 48px;
  padding: 0 24px;
}
.detail-card :deep(.arco-card-body) {
  padding: 20px 24px;
}
.detail-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px 42px;
  padding: 0;
}
.detail-item {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 12px;
  align-items: start;
  min-height: 38px;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border-1);
}
.detail-item-wide {
  grid-column: 1 / -1;
}
.detail-label {
  color: var(--color-text-3);
  white-space: nowrap;
}
.detail-value {
  color: var(--color-text-1);
  white-space: pre-wrap;
  word-break: break-word;
}
.detail-relation-value {
  display: grid;
  gap: 4px;
}
.json-value {
  max-height: 360px;
  margin: 0;
  padding: 12px;
  overflow: auto;
  color: var(--color-text-1);
  background: var(--color-fill-1);
  border-radius: 6px;
  white-space: pre-wrap;
}
@media (max-width: 1280px) {
  .detail-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 760px) {
  .detail-card :deep(.arco-card-header),
  .detail-card :deep(.arco-card-body) {
    padding-right: 16px;
    padding-left: 16px;
  }
  .detail-grid {
    grid-template-columns: 1fr;
    gap: 4px;
  }
  .detail-item,
  .detail-item-wide {
    grid-column: auto;
  }
}
</style>
