<template>
  <!-- 如果是单页模式，直接显示单页详情组件 -->
  <DefaultSingle v-if="isSinglePage" />
  <div v-else class="page">
    <!-- 头部，与 AI 智能体列表一致的结构 -->
    <div class="page-header">
      <div class="header-left">
        <h2>{{ t_ctx(title) }}</h2>
      </div>
      <div class="header-right">
        <!-- 工具栏覆盖组件 - 支持两种接口：context 或 props -->
        <component
          v-if="toolbarComponent"
          :is="toolbarComponent"
          :context="{
            entity,
            filters,
            searchQuery,
            viewMode,
            selectedKeys,
            loading,
            rows,
            reload,
            createRecordHandler,
            handleDeleteSelected,
            router,
            t,
            canEdit: canEditList,
            canDelete: canDeleteSelected,
          }"
          :entity="entity"
          :search-query="searchQuery"
          :view-mode="viewMode"
          :selected-keys="selectedKeys"
          :loading="loading"
          @update:search-query="searchQuery = $event"
          @update:view-mode="viewMode = $event"
          @reload="reload"
          @create="createRecordHandler"
          @delete-selected="handleDeleteSelected"
        />
        <DefaultListToolbar
          v-else
          :entity="entity"
          :search-query="searchQuery"
          :view-mode="viewMode"
          :selected-keys="selectedKeys"
          :loading="loading"
          :can-edit="canEditList"
          :can-delete="canDeleteSelected"
          @update:search-query="searchQuery = $event"
          @update:view-mode="viewMode = $event"
          @reload="reload"
          @create="createRecordHandler"
          @delete-selected="handleDeleteSelected"
        />
      </div>
    </div>

    <div class="page-content">
      <!-- 过滤栏覆盖组件 - 支持两种接口：context 或 props -->
      <component
        v-if="filterBarComponent"
        :is="filterBarComponent"
        :context="{
          fields: metaFields,
          filters,
          onFilterChange
        }"
        :fields="metaFields"
        v-model:filters="filters"
        @filter-change="onFilterChange"
      />
      <!-- 默认过滤栏 -->
      <div v-else-if="!isSinglePage && metaFields.length > 0" class="filter-bar-container">
        <DefaultListFilterBar 
          :fields="metaFields"
          v-model:filters="filters"
          v-model:sort-by="sortBy"
          v-model:sort-order="sortOrder"
          :page-meta="pageMeta"
          @filter-change="onFilterChange"
          @sort-change="onSortChange"
        />
      </div>

      <!-- 列表页优化：保留上次内容，显示轻微加载指示，提供更好的连续浏览体验 -->
      <div class="list-content-wrapper" :class="{ 'loading-state': loading }">
        <!-- 加载指示（不遮挡内容） -->
        <div v-if="loading && rows.length === 0" class="loading-full">
          <i class="fa fa-spinner fa-spin"></i> {{ t('Loading...') }}
        </div>
        <div v-else>
          <!-- 顶部轻微加载指示（仅在已有数据时显示） -->
          <div v-if="loading && rows.length > 0" class="loading-overlay">
            <i class="fa fa-spinner fa-spin"></i>
          </div>
          <!-- 卡片视图 -->
          <div v-if="viewMode === 'card'" class="agent-grid">
          <div 
            v-for="row in filteredRows" 
            :key="row.name" 
            class="agent-card" 
            :class="{ 
              selected: selectedKeys.includes(row.name),
              'no-permission': !checkReadPermission(row)
            }"
            @click="openDetail(row.name)"
          >
            <div class="card-checkbox">
              <input 
                type="checkbox" 
                :checked="selectedKeys.includes(row.name)"
                @click.stop="toggleSelection(row.name)"
              />
            </div>
            <!-- 卡片图片 -->
            <div v-if="imageFieldName && getImageUrl(row) && !imageLoadErrors.has(row.name)" class="card-image">
              <img 
                :src="getImageUrl(row) || ''" 
                :alt="row[primaryLabel] || row.name"
                loading="lazy"
                decoding="async"
                @error="(e) => handleImageError(e, row.name)"
                @load="(e) => handleImageLoad(e, row.name)"
              />
            </div>
            <div class="card-content">
              <div class="info" @click.stop="openDetail(row.name)">
                <div class="title">{{ row[primaryLabel] || row.name }}</div>
                <div class="desc" v-if="!hideIdInList">{{ row.name }}</div>
                <div class="meta">
                  <template v-for="f in cardBadges" :key="f.key">
                    <!-- Select字段使用独立的span，不包裹在.badge中 -->
                    <span 
                      v-if="isSelectField(f.key) && row[f.key] !== null && row[f.key] !== undefined && row[f.key] !== ''"
                      class="select-badge" 
                      :style="{ 
                        backgroundColor: getSelectBadgeColor(f.key, row[f.key]),
                        color: getSelectBadgeTextColor(f.key, row[f.key])
                      }"
                    >
                      {{ formatDisplayValue(row[f.key], f.key, row) }}
                    </span>
                    <!-- 其他字段使用.badge包裹，只在有值时渲染 -->
                    <span v-else-if="row[f.key] !== null && row[f.key] !== undefined && row[f.key] !== ''" class="badge">
                      <template v-if="isBooleanField(f.key) && (row[f.key] === 1 || row[f.key] === 0 || typeof row[f.key] === 'boolean')">
                        <span v-if="row[f.key] === 1 || row[f.key] === true" class="boolean-true">✓</span>
                        <span v-else class="boolean-false">○</span>
                      </template>
                      <template v-else-if="isIconField(f.key) && row[f.key]">
                        <Icon :icon="row[f.key]" :width="20" :height="20" class="icon-gray" />
                      </template>
                      <template v-else>{{ formatDisplayValue(row[f.key], f.key, row) }}</template>
                    </span>
                  </template>
                </div>
              </div>
            </div>
            <!-- 操作列覆盖组件（卡片视图） - 支持两种接口：context 或 props -->
            <component
              v-if="actionsComponent"
              :is="actionsComponent"
              :context="{
                row,
                entity,
                openDetail,
                editRecord,
                deleteRecord,
                router,
                t,
                viewMode: 'card'
              }"
              :row="row"
              :entity="entity"
              view-mode="card"
              @view="openDetail(row.name)"
              @edit="editRecord(row)"
              @delete="deleteRecord(row.name)"
            />
            <!-- 默认操作按钮 -->
            <DefaultListActions
              v-else
              :row="row"
              :entity="entity"
              view-mode="card"
              @view="openDetail(row.name)"
              @edit="editRecord(row)"
              @delete="deleteRecord(row.name)"
              @like-toggled="() => {}"
            />
          </div>
          </div>
          <div v-if="viewMode === 'card'" class="list-pagination">
            <n-pagination v-model:page="page" :page-count="pageCount" size="small" />
          </div>

          <!-- 列表视图 -->
          <div v-else class="agent-list" :class="{ 'has-image': imageFieldName }">
          <div class="list-header" :style="{ gridTemplateColumns }">
            <div class="col-checkbox">
              <input
                type="checkbox"
                :checked="selectedKeys.length === filteredRows.length && filteredRows.length > 0"
                :indeterminate="selectedKeys.length > 0 && selectedKeys.length < filteredRows.length"
                @change="toggleSelectAll"
              />
            </div>
            <!-- 列表图片列 -->
            <div v-if="imageFieldName" class="col-image">{{ t('Image') }}</div>
            <div v-for="col in displayColumns" :key="col.key" :class="[`col-${col.key}`, { 'col-collapsed': hideIdInList && col.key === 'name' }]"><template v-if="!(hideIdInList && col.key === 'name')">{{ t_ctx(col.title) }}</template></div>
            <div class="col-actions">{{ t('Actions') }}</div>
          </div>
          <div class="list-body">
            <div
              v-for="row in filteredRows"
              :key="row.name"
              class="list-item"
              :style="{ gridTemplateColumns }"
              :class="{ 
                selected: selectedKeys.includes(row.name),
                'no-permission': !checkReadPermission(row)
              }"
              @click="openDetail(row.name)"
            >
              <div class="col-checkbox">
                <input
                  type="checkbox"
                  :checked="selectedKeys.includes(row.name)"
                  @click.stop="toggleSelection(row.name)"
                />
              </div>
              <!-- 列表图片 -->
              <div v-if="imageFieldName" class="col-image" @click.stop="openDetail(row.name)">
                <img 
                  v-if="getImageUrl(row) && !imageLoadErrors.has(row.name)" 
                  :src="getImageUrl(row) || ''" 
                  :alt="row[primaryLabel] || row.name"
                  loading="lazy"
                  decoding="async"
                  @error="(e) => handleImageError(e, row.name)"
                  @load="(e) => handleImageLoad(e, row.name)"
                />
                <span v-else class="image-placeholder">—</span>
              </div>
              <div v-for="col in displayColumns" :key="col.key" :class="[`col-${col.key}`, { 'col-collapsed': hideIdInList && col.key === 'name' }]" @click.stop="openDetail(row.name)" :title="!(hideIdInList && col.key === 'name') ? formatDisplayValue(row[col.key], col.key, row) : ''">
                <template v-if="hideIdInList && col.key === 'name'"><!-- hidden --></template>
                <template v-else-if="isBooleanField(col.key) && (row[col.key] === 1 || row[col.key] === 0 || typeof row[col.key] === 'boolean')">
                  <span v-if="row[col.key] === 1 || row[col.key] === true" class="boolean-true">✓</span>
                  <span v-else class="boolean-false">○</span>
                </template>
                <template v-else-if="isIconField(col.key) && row[col.key]">
                  <Icon :icon="row[col.key]" :width="20" :height="20" class="icon-gray" />
                </template>
                <template v-else-if="isSelectField(col.key) && row[col.key] !== null && row[col.key] !== undefined && row[col.key] !== ''">
                  <span 
                    class="select-badge" 
                    :style="{ 
                      backgroundColor: getSelectBadgeColor(col.key, row[col.key]),
                      color: getSelectBadgeTextColor(col.key, row[col.key])
                    }"
                  >
                    {{ formatDisplayValue(row[col.key], col.key, row) }}
                  </span>
                </template>
                <template v-else-if="row[col.key] !== null && row[col.key] !== undefined && row[col.key] !== ''">{{ formatDisplayValue(row[col.key], col.key, row) }}</template>
              </div>
              <!-- 操作列覆盖组件 - 支持两种接口：context 或 props -->
              <component
                v-if="actionsComponent"
                :is="actionsComponent"
                :context="{
                  row,
                  entity,
                  openDetail,
                  editRecord,
                  deleteRecord,
                  router,
                  t,
                  viewMode: 'list'
                }"
                :row="row"
                :entity="entity"
                view-mode="list"
                @view="openDetail(row.name)"
                @edit="editRecord(row)"
                @delete="deleteRecord(row.name)"
              />
              <!-- 默认操作按钮 -->
              <DefaultListActions
                v-else
                :row="row"
                :entity="entity"
                view-mode="list"
                @view="openDetail(row.name)"
                @edit="editRecord(row)"
                @delete="deleteRecord(row.name)"
                @like-toggled="() => {}"
              />
            </div>
          </div>
          <div v-if="viewMode === 'list'" class="list-pagination">
            <n-pagination v-model:page="page" :page-count="pageCount" size="small" />
          </div>
        </div>
        </div>
      </div>
    </div>
  </div>
  
  <!-- 创建PageType模态对话框 -->
  <CreatePageTypeModal 
    v-model:show="showCreateModal" 
    @created="handleCreated"
  />
</template>

<script setup lang="ts">
import { onMounted, ref, computed, watch, shallowRef, markRaw } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NPagination, NButton, NSelect, useMessage, useDialog } from 'naive-ui'
import { Icon } from '@iconify/vue'
import axios from 'axios'
import { t, createT } from '@/shared/i18n'
import { formatDateTimeInTimezone } from '@/shared/utils/timezone'
import { usePageTypeSlug } from '@/shared/utils/slug'
import { isSinglePageType } from '@/shared/utils/pagetype'
import { getPageTypeMeta, searchWidget } from '@/shared/api/common'
import DefaultSingle from '@/core/pagetype/default_single.vue'
import DefaultListToolbar from '@/core/pagetype/default_list_toolbar.vue'
import DefaultListFilterBar from '@/core/pagetype/default_list_filterbar.vue'
import DefaultListActions from '@/core/pagetype/default_list_actions.vue'
import DefaultListSortSelector from '@/core/pagetype/default_list_sort_selector.vue'
import CreatePageTypeModal from '@/core/components/CreatePageTypeModal.vue'
import {
  resolvePagetypeListToolbarOverride,
  resolvePagetypeListFilterBarOverride,
  resolvePagetypeListActionsOverride
} from '@/core/registry/pagetypeOverride'
import { usePermissionStore } from '@/shared/stores/permissions'

const route = useRoute()
const router = useRouter()
const message = useMessage()
const dialog = useDialog()
const permissionStore = usePermissionStore()

// 使用组合式函数处理URL slug
const { pagetypeSlug, entity } = usePageTypeSlug(route)
const t_ctx = createT(() => entity.value)
const title = computed(() => entity.value)
const canEditList = computed(() => permissionStore.canWrite(entity.value))

// 基于选中行的行级权限判断是否可批量删除
// 后端 _can_delete 已根据 if_owner（仅创建者）等约束计算
const canDeleteSelected = computed(() => {
  if (selectedKeys.value.length === 0) return false
  return selectedKeys.value.some(key => {
    const row = rows.value.find((r: any) => r.name === key)
    return row && (row._can_delete === 1 || row._can_delete === undefined)
  })
})

// 覆盖组件引用（子组件覆盖，整体覆盖由 ListPage.vue 处理）
const toolbarComponent = shallowRef<any | null>(null)
const filterBarComponent = shallowRef<any | null>(null)
const actionsComponent = shallowRef<any | null>(null)

// Link字段的title_field映射（对齐旧版list_view.js的link_field_title_fields）
// 格式: { fieldname: titleFieldName }，例如 { customer: "customer_name" }
// 仅当关联PageType启用了show_title_field_in_link且title_field不为name时才填充
const linkFieldTitleFields = ref<Record<string, string>>({})

// 检查是否为单页模式
const isSinglePage = ref(false)
const searchQuery = ref('')
const loading = ref(false)
const rows = ref<any[]>([])
const page = ref(1)
const pageSize = ref(parseInt(localStorage.getItem('itemsPerPage') || '10'))
const pageCount = computed(() => {
  // 确保有总数数据时才计算分页
  if (total.value === 0 || rows.value.length === 0) return 1
  return Math.max(1, Math.ceil(total.value / pageSize.value))
})
const total = ref(0)
const selectedKeys = ref<string[]>([])
const viewMode = ref<'card' | 'list'>(
  (localStorage.getItem(`genericListViewMode:${entity.value}`) as 'card' | 'list') || 'list'
)

// List state storage key
const listStateKey = computed(() => `list-state:${entity.value}`)

// Save list state before navigating to detail
function saveListState() {
  const state = {
    page: page.value,
    filters: filters.value,
    sortBy: sortBy.value,
    sortOrder: sortOrder.value,
    searchQuery: searchQuery.value,
    rowNames: rows.value.map(r => r.name)
  }
  sessionStorage.setItem(listStateKey.value, JSON.stringify(state))
}

// Restore list state when coming back from detail (filters, sort, search)
// Note: page is controlled by URL, not sessionStorage
function restoreListState() {
  const saved = sessionStorage.getItem(listStateKey.value)
  if (saved) {
    try {
      const state = JSON.parse(saved)
      // 只恢复 filters、sortBy、sortOrder、searchQuery，不恢复 page
      if (state.filters) filters.value = state.filters
      if (state.sortBy) sortBy.value = state.sortBy
      if (state.sortOrder) sortOrder.value = state.sortOrder
      if (state.searchQuery) searchQuery.value = state.searchQuery
    } catch (e) {
      console.warn('Failed to restore list state:', e)
    }
  }
}

// 排序条件（对齐旧版默认值：modified desc）
const sortBy = ref<string>('modified')
const sortOrder = ref<'asc' | 'desc'>('desc')

// 过滤条件
const filters = ref<Record<string, any>>({})

// PageType创建对话框
const showCreateModal = ref(false)

// 处理创建成功
function handleCreated(name: string) {
  openDetail(name)
}

// 监听过滤条件变化
function onFilterChange() {
  page.value = 1 // 重置到第一页
  loadData()
}

// 监听排序变化
function onSortChange(newSortBy: string, newSortOrder: 'asc' | 'desc') {
  sortBy.value = newSortBy
  sortOrder.value = newSortOrder
  page.value = 1 // 重置到第一页
  loadData()
}

const hideIdInList = computed(() => pageMeta.value?.hide_id_in_list === 1 || pageMeta.value?.hide_id_in_list === true)

const displayColumns = computed(() => {
  // 生成列表列：严格使用 in_list_view 属性，排除分隔类
  const isDisplayable = (f: any) => !['Section Break', 'Column Break', 'Tab Break'].includes(f.fieldtype)
  const display = metaFields.value.filter((f: any) => f.in_list_view && isDisplayable(f))
  
  // 不再回退到显示所有字段，如果没有设置 in_list_view，则只显示 name
  const cols: any[] = display.slice(0, 30).map((f: any) => {
    // 将 columns 属性转换为宽度百分比 (columns 范围 1-11，乘以 8%)
    // 参考 Table.vue: { width: (size * 8) + '%' }
    const widthPercent = f.columns ? Math.min(f.columns * 8, 88) : undefined
    return { 
      title: f.label || f.fieldname, 
      key: f.fieldname,
      width: widthPercent,
      fieldtype: f.fieldtype
    }
  })
  
  if (!cols.find(c => c.key === 'name')) cols.unshift({ title: 'ID', key: 'name' })
  
  if (!cols.find(c => c.key === 'modified')) {
    cols.push({ title: 'Modified', key: 'modified' })
  }
  
  if (pageMeta.value?.show_owner_in_list && !cols.find(c => c.key === 'owner')) {
    cols.push({ title: 'Owner', key: 'owner' })
  }
  
  return cols
})

// 计算 grid-template-columns 样式
const gridTemplateColumns = computed(() => {
  const parts: string[] = ['40px'] // checkbox 列
  
  // 图片列
  if (imageFieldName.value) {
    parts.push('minmax(50px, 50px)')
  }
  
  // 数据列：按原始顺序处理，有 width 用固定宽度，无 width 用自动分配
  displayColumns.value.forEach((c: any) => {
    // hide_id_in_list 时 name 列折叠为 0 宽度
    if (hideIdInList.value && c.key === 'name') {
      parts.push('0px')
    } else if (c.width) {
      parts.push(`minmax(80px, ${c.width}%)`)
    } else {
      parts.push('minmax(100px, 1fr)')
    }
  })
  
  // 操作列
  parts.push('170px')
  
  return parts.join(' ')
})

const primaryLabel = computed(() => {
  const f = metaFields.value.find((x: any) => x.in_list_view && x.fieldname !== 'name')
  return f?.fieldname || 'name'
})
const cardBadges = computed(() => {
  // 显示所有 displayColumns 中的字段，除了已经显示的 primaryLabel 和 name
  const keys = displayColumns.value.map((c: any) => c.key).filter((k: string) => k && k !== 'actions' && k !== primaryLabel.value && k !== 'name')
  return keys.map((k: string) => ({ key: k }))
})

// 获取图片字段名
const imageFieldName = computed(() => {
  return pageMeta.value?.image_field || ''
})

const imageLoadErrors = ref<Set<string>>(new Set())

function getImageUrl(row: any): string | null {
  if (!imageFieldName.value) return null
  const imageValue = row[imageFieldName.value]
  if (!imageValue) return null
  
  if (typeof imageValue === 'string') {
    return imageValue.trim() || null
  }
  
  if (typeof imageValue === 'object') {
    const url = imageValue.file_url || imageValue.url || imageValue.value
    if (typeof url === 'string' && url.trim()) {
      return url.trim()
    }
  }
  
  return null
}

function handleImageError(_event: Event, rowName: string) {
  imageLoadErrors.value.add(rowName)
}

function handleImageLoad(_event: Event, rowName: string) {
  imageLoadErrors.value.delete(rowName)
}

const metaFields = ref<any[]>([])
const pageMeta = ref<any>({})
const pageTypeConfigCache = ref<Record<string, any>>({})

async function loadMeta() {
  loading.value = true
  try {
    // 使用后端API获取元数据，避免权限问题
    const result = await getPageTypeMeta(entity.value)
    
    if (result.success && result.data) {
      metaFields.value = result.data.fields || []
      pageMeta.value = result.data // 保存完整的pageMeta，包含image_field等配置
      
      // 检查是否为单页模式
      isSinglePage.value = Boolean(result.data.issingle === 1 || result.data.issingle === true)
      
      // 初始化排序（对齐旧版 sort_selector.js line 106-114）
      if (result.data.sort_field) {
        sortBy.value = result.data.sort_field
        sortOrder.value = (result.data.sort_order || 'desc').toLowerCase() as 'asc' | 'desc'
      } else {
        // 默认值：modified desc
        sortBy.value = 'modified'
        sortOrder.value = 'desc'
      }

      // 对齐旧版list_view.js：预加载Link字段的title_field配置
      // 在loadData之前完成，确保fields参数中可以包含JOIN查询
      await preloadLinkFieldTitleConfig()
    } else {
      message.error(result.message || t('Failed to load metadata'))
      console.error('Load metadata failed:', result.message)
    }
  } catch (error) {
    message.error(t('Failed to load metadata'))
    console.error('Load metadata error:', error)
  } finally {
    loading.value = false
  }
}

// 获取页面类型配置
async function getPageTypeConfig(pagetype: string) {
  if (!pagetype) return {}
  
  // 检查缓存
  if (pageTypeConfigCache.value[pagetype]) {
    return pageTypeConfigCache.value[pagetype]
  }
  
  try {
    // 使用后端API获取元数据
    const result = await getPageTypeMeta(pagetype)
    
    if (result.success && result.data) {
      const config = result.data
      pageTypeConfigCache.value[pagetype] = config
      return config
    } else {
      console.error('获取页面类型配置失败:', result.message)
      return {}
    }
  } catch (error) {
    console.error('获取页面类型配置失败:', error)
    return {}
  }
}

// 对齐旧版list_view.js set_fields()：预加载Link字段的title_field配置
// 在loadData之前调用，确保fields参数中可以包含JOIN查询
async function preloadLinkFieldTitleConfig() {
  linkFieldTitleFields.value = {}
  
  const linkFields = metaFields.value.filter((f: any) => f.fieldtype === 'Link' && f.options && f.in_list_view)
  if (linkFields.length === 0) return
  
  await Promise.all(linkFields.map(async (field: any) => {
    try {
      const config = await getPageTypeConfig(field.options)
      if (config.show_title_field_in_link && config.title_field && config.title_field !== 'name') {
        linkFieldTitleFields.value[field.fieldname] = config.title_field
      }
    } catch (error) {
      console.warn(`获取${field.options}的配置失败:`, error)
    }
  }))
}

async function loadData() {
  loading.value = true
  try {
    const listUrl = `/api/data/${encodeURIComponent(entity.value)}`
    // 仅请求所需字段，避免接口默认不返回
    let fieldNames = displayColumns.value.map((c: any) => c.key).filter((k: string) => k && k !== 'actions')
    // 如果配置了image_field，确保包含该字段
    if (imageFieldName.value && !fieldNames.includes(imageFieldName.value)) {
      fieldNames.push(imageFieldName.value)
    }
    
    // 确保包含 modified 字段用于显示修改时间
    if (!fieldNames.includes('modified')) {
      fieldNames.push('modified')
    }
    
    // 确保包含 _liked_by 字段用于收藏图标显示
    if (!fieldNames.includes('_liked_by')) {
      fieldNames.push('_liked_by')
    }
    
    // 对齐旧版list_view.js get_fields()：Link字段的title_field通过JOIN查询
    // 例如: customer.customer_name as customer_customer_name
    const linkTitleFields: string[] = []
    Object.entries(linkFieldTitleFields.value).forEach(([fieldname, titleField]) => {
      linkTitleFields.push(`${fieldname}.${titleField} as ${fieldname}_${titleField}`)
    })
    
    // 构建过滤参数
    // 多请求1条数据，用于准确判断是否有下一页
    const params: any = { 
      fields: JSON.stringify([...fieldNames, ...linkTitleFields]),
      limit_start: (page.value - 1) * pageSize.value, 
      limit_page_length: pageSize.value + 1,
      order_by: `${sortBy.value} ${sortOrder.value}`
    }
    
    // 添加过滤条件
    const filterConditions: any[] = []
    
    // 翻译搜索标记
    let needsTranslationSearch = false
    let translationSearchValue = ''
    
    // 先处理非Link字段的过滤条件
    const linkFieldFilters: Array<{ fieldName: string; value: string; fieldMeta: any }> = []
    
    Object.entries(filters.value).forEach(([fieldName, value]) => {
      if (value !== null && value !== undefined && value !== '' && 
          !(Array.isArray(value) && value.length === 0)) {
        if (Array.isArray(value)) {
          // 多选字段使用 in 操作符
          filterConditions.push([fieldName, 'in', value])
        } else {
          // 根据字段类型选择操作符
          const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
          const fieldType = fieldMeta?.fieldtype || ''
          
          // 特殊处理：name字段（ID）支持翻译搜索
          // 对于标记为translated_pagetype的PageType，需要支持根据翻译值搜索
          if (fieldName === 'name' && typeof value === 'string') {
            // 将name字段搜索统一延迟处理，检查是否需要翻译搜索
            linkFieldFilters.push({ fieldName, value: value as string, fieldMeta: { fieldtype: 'TranslatedName' } })
          }
          // Link字段类型：需要同时匹配字段值和title_field
          else if (fieldType === 'Link' && typeof value === 'string' && fieldMeta?.options) {
            // 收集Link字段过滤条件，稍后处理
            linkFieldFilters.push({ fieldName, value: value as string, fieldMeta })
          } else if (['Data', 'Text', 'Long Text', 'Small Text', 'Comment'].includes(fieldType)) {
            // 文本类型字段使用 like 操作符进行模糊搜索
            if (typeof value === 'string') {
              filterConditions.push([fieldName, 'like', `%${value}%`])
            }
          } else {
            // 其他类型字段使用精确匹配
            filterConditions.push([fieldName, '=', value])
          }
        }
      }
    })
    
    // 处理Link字段的过滤：需要搜索关联记录的title_field
    for (const linkFilter of linkFieldFilters) {
      const { fieldName, value, fieldMeta } = linkFilter
      
      // 特殊处理：name字段翻译搜索
      // 对于标记了translated_pagetype的PageType，使用search_widget API
      if (fieldMeta.fieldtype === 'TranslatedName' && fieldName === 'name') {
        // 检查当前PageType是否标记为translated_pagetype
        const isTranslatedPagetype = pageMeta.value?.translated_pagetype === 1 || 
                                     pageMeta.value?.translated_pagetype === true
        
        if (!isTranslatedPagetype) {
          // 如果不是translated_pagetype，使用普通like搜索
          filterConditions.push([fieldName, 'like', `%${value}%`])
          continue
        }
        
        // 对于translated_pagetype，标记为需要使用search_widget
        // 在后续处理中将所有过滤条件传给search_widget，而不是get_list
        needsTranslationSearch = true
        translationSearchValue = value
        continue
      }
      
      const linkedPagetype = fieldMeta.options
      
      try {
        // 获取关联pagetype的配置
        const config = await getPageTypeConfig(linkedPagetype)
        const titleField = config.title_field || 'name'
        
        // 构建匹配的name值列表
        const matchedNames = new Set<string>()
        
        // 1. 先匹配Link字段值（name字段）本身
        if (value) {
          matchedNames.add(value) // 精确匹配
          // 也支持模糊匹配name字段
        }
        
        // 2. 如果title_field不是name且启用了show_title_field_in_link，搜索title_field
        if (titleField !== 'name' && config.show_title_field_in_link) {
          try {
            // 搜索关联pagetype的title_field
            const searchFilters = [[titleField, 'like', `%${value}%`]]
            const searchResult = await axios.get(`/api/data/${encodeURIComponent(linkedPagetype)}`, {
              params: {
                fields: JSON.stringify(['name']),
                filters: JSON.stringify(searchFilters),
                limit_page_length: 100 // 限制最多100条，避免性能问题
              }
            })
            
            const matchedRecords = searchResult.data?.data || []
            matchedRecords.forEach((record: any) => {
              if (record.name) {
                matchedNames.add(record.name)
              }
            })
          } catch (error) {
            console.warn(`搜索${linkedPagetype}的title_field失败:`, error)
          }
        } else if (titleField === 'name') {
          // 如果title_field就是name，直接使用like匹配
          // 使用OR条件：匹配name本身或name字段like
          // 由于后端可能不支持OR，我们使用in操作符，包含value和可能的匹配值
          // 先搜索匹配的记录
          try {
            const searchFilters = [['name', 'like', `%${value}%`]]
            const searchResult = await axios.get(`/api/data/${encodeURIComponent(linkedPagetype)}`, {
              params: {
                fields: JSON.stringify(['name']),
                filters: JSON.stringify(searchFilters),
                limit_page_length: 100
              }
            })
            
            const matchedRecords = searchResult.data?.data || []
            matchedRecords.forEach((record: any) => {
              if (record.name) {
                matchedNames.add(record.name)
              }
            })
          } catch (error) {
            console.warn(`搜索${linkedPagetype}的name字段失败:`, error)
          }
        }
        
        // 如果有匹配的name值，使用in操作符
        if (matchedNames.size > 0) {
          filterConditions.push([fieldName, 'in', Array.from(matchedNames)])
        } else {
          // 如果没有匹配值，使用like匹配字段值本身
          filterConditions.push([fieldName, 'like', `%${value}%`])
        }
      } catch (error) {
        console.warn(`处理Link字段${fieldName}过滤失败，使用字段值匹配:`, error)
        // 降级方案：直接使用like匹配字段值
        filterConditions.push([fieldName, 'like', `%${value}%`])
      }
    }
    
    if (filterConditions.length > 0) {
      params.filters = JSON.stringify(filterConditions)
    }
    
    // 根据是否需要翻译搜索选择不同的API
    if (needsTranslationSearch) {
      // 使用search_widget API（后端自动处理翻译搜索和分页）
      const searchResult = await searchWidget(
        entity.value,
        translationSearchValue,
        {
          page_length: pageSize.value + 1,
          start: (page.value - 1) * pageSize.value,
          filters: filterConditions.length > 0 ? filterConditions : undefined
        }
      )
      
      if (searchResult.success) {
        const allRows = searchResult.data || []
        const hasMore = allRows.length > pageSize.value
        rows.value = hasMore ? allRows.slice(0, pageSize.value) : allRows
        total.value = (page.value - 1) * pageSize.value + rows.value.length + (hasMore ? 1 : 0)
      } else {
        message.error(searchResult.message || t('Search failed'))
        rows.value = []
        total.value = 0
      }
    } else {
      // 使用普通的get_list API
      const res = await axios.get(listUrl, { 
        params
      })
      const allRows = res.data?.data || []
      
      if (res.data?.total) {
        // 后端返回了total，直接使用
        rows.value = allRows
        total.value = res.data.total
      } else {
        // 后端没有返回total，通过多请求的1条数据判断
        const hasMore = allRows.length > pageSize.value
        rows.value = hasMore ? allRows.slice(0, pageSize.value) : allRows
        // 精确计算total
        total.value = (page.value - 1) * pageSize.value + rows.value.length + (hasMore ? 1 : 0)
      }
    }
  } catch (error) {
    console.error('Load data error:', error)
    message.error(t('Load failed'))
  } finally {
    loading.value = false
  }
}

onMounted(async () => {
  // 解析子组件覆盖（工具栏、过滤栏、操作栏）
  const listToolbarComp = await resolvePagetypeListToolbarOverride(pagetypeSlug.value)
  toolbarComponent.value = listToolbarComp ? markRaw(listToolbarComp) : null
  
  const listFilterBarComp = await resolvePagetypeListFilterBarOverride(pagetypeSlug.value)
  filterBarComponent.value = listFilterBarComp ? markRaw(listFilterBarComp) : null
  
  const listActionsComp = await resolvePagetypeListActionsOverride(pagetypeSlug.value)
  actionsComponent.value = listActionsComp ? markRaw(listActionsComp) : null
  
  // 从 sessionStorage 恢复列表状态（filters、sort 等，但 page 由 URL 控制）
  restoreListState()
  
  // 从 URL query 参数读取页码（URL 驱动机制）
  const urlPage = route.query.page
  if (urlPage) {
    const parsed = parseInt(String(urlPage), 10)
    if (!isNaN(parsed) && parsed > 0) {
      page.value = parsed
    }
  } else if (!sessionStorage.getItem(listStateKey.value)) {
    // URL 无 page 参数且无历史状态时，强制从第1页开始
    page.value = 1
  }
  
  await loadMeta()
  // 只有在非单页模式下才加载列表数据
  if (!isSinglePage.value) {
    await loadData()
  }
})

// 监听分页变化，同步更新URL（URL驱动机制）
watch([page], () => {
  loadData()
  // 更新URL的page参数，使用replace避免产生历史记录
  const currentPage = route.query.page
  const newPage = String(page.value)
  if (currentPage !== newPage) {
    router.replace({
      query: { ...route.query, page: page.value > 1 ? page.value : undefined }
    }).catch(() => {
      // 忽略取消导航的错误
    })
  }
})

// 监听路由参数变化，当entity变化时重新加载数据
watch(() => route.params.entity, async (newEntity, oldEntity) => {
  if (newEntity !== oldEntity) {
    // 重新解析子组件覆盖
    const listToolbarComp = await resolvePagetypeListToolbarOverride(String(newEntity))
    toolbarComponent.value = listToolbarComp ? markRaw(listToolbarComp) : null
    
    const listFilterBarComp = await resolvePagetypeListFilterBarOverride(String(newEntity))
    filterBarComponent.value = listFilterBarComp ? markRaw(listFilterBarComp) : null
    
    const listActionsComp = await resolvePagetypeListActionsOverride(String(newEntity))
    actionsComponent.value = listActionsComp ? markRaw(listActionsComp) : null
    
    // 重置分页和搜索，URL的page参数也清除
    page.value = 1
    searchQuery.value = ''
    selectedKeys.value = []
    filters.value = {}
    // 清除URL中的page参数
    if (route.query.page) {
      router.replace({ query: { ...route.query, page: undefined } }).catch(() => {})
    }
    // 根据新entity重新加载视图模式（重要：修复全局生效的问题）
    viewMode.value = (localStorage.getItem(`genericListViewMode:${entity.value}`) as 'card' | 'list') || 'list'
    // 重新加载元数据和数据
    await loadMeta() // loadMeta中会加载新entity的缓存
    // 只有在非单页模式下才加载列表数据
    if (!isSinglePage.value) {
      await loadData()
    }
  }
}, { immediate: false })

// 监听视图模式变化，保存到本地
watch(viewMode, (newMode) => {
  localStorage.setItem(`genericListViewMode:${entity.value}`, newMode)
})

function reload() {
  loadData()
}

const filteredRows = computed(() => {
  if (!searchQuery.value) return rows.value
  const q = searchQuery.value.toLowerCase()
  const keys = displayColumns.value.map((c: any) => c.key).filter((k: string) => k && k !== 'actions' && !(hideIdInList.value && k === 'name'))
  return rows.value.filter((r: any) => keys.some((k: string) => String(r[k] ?? '').toLowerCase().includes(q)))
})

function toggleSelection(name: string) {
  const i = selectedKeys.value.indexOf(name)
  if (i > -1) selectedKeys.value.splice(i, 1)
  else selectedKeys.value.push(name)
}

function toggleSelectAll() {
  if (selectedKeys.value.length === filteredRows.value.length) {
    selectedKeys.value = []
  } else {
    selectedKeys.value = filteredRows.value.map(row => row.name)
  }
}

// 检查记录是否有读取权限（基于后端返回的权限标记）
function checkReadPermission(row: any): boolean {
  // 后端返回的 _can_read 字段，1 表示有权限，0 表示无权限
  return row._can_read === 1 || row._can_read === undefined // 如果没有此字段，默认允许访问
}

function openDetail(name: string) {
  // 查找对应的记录
  const row = rows.value.find(r => r.name === name)
  
  // 检查权限，如果无权限，直接显示弹窗
  if (row && !checkReadPermission(row)) {
    message.error(t('You do not have enough permissions to access this resource. Please contact your manager to get access.'), {
      duration: 5000
    })
    return
  }
  
  // Save list state before navigating
  saveListState()
  
  // 通过 history.state 传递当前页码，返回时恢复
  const state = { ...history.state, _listPage: page.value }
  
  // 跳转到详情页（不携带query参数，保持URL简洁）
  router.push({ 
    name: 'PageTypeDetail', 
    params: { entity: pagetypeSlug.value, id: name },
    state
  })
}

async function handleDeleteSelected() {
  if (selectedKeys.value.length === 0) return
  
  dialog.warning({
    title: t('Delete Selected Records'),
    content: `${t('Are you sure you want to delete')} ${selectedKeys.value.length} ${t('selected record(s)? This action cannot be undone.')}`,
    positiveText: t('Delete'),
    negativeText: t('Cancel'),
    onPositiveClick: async () => {
      loading.value = true
      try {
        const { deleteRecords } = await import('../../shared/api/common')
        const res = await deleteRecords(entity.value, selectedKeys.value)
        if (res.success) {
          message.success(res.message || t('Deleted successfully'))
          selectedKeys.value = []
          await loadData()
        } else {
          message.error(res.message || t('Delete failed'))
        }
      } catch (error) {
        message.error(t('Delete failed'))
        console.error('Delete error:', error)
      } finally {
        loading.value = false
      }
    }
  })
}

function createRecordHandler() {
  // 特殊处理：PageType需要先输入名称
  if (entity.value === 'PageType') {
    showCreatePageTypeDialog()
    return
  }
  
  // 普通记录：直接生成临时name并打开
  const randomStr = Math.random().toString(36).substring(2, 12)
  const tempName = `new-${pagetypeSlug.value}-${randomStr}`
  openDetail(tempName)
}

// 显示创建PageType对话框
function showCreatePageTypeDialog() {
  showCreateModal.value = true
}

function editRecord(row: any) {
  openDetail(row.name)
}

async function deleteRecord(name: string) {
  dialog.warning({
    title: t('Delete Record'),
    content: t('Are you sure you want to delete this record? This action cannot be undone.'),
    positiveText: t('Delete'),
    negativeText: t('Cancel'),
    onPositiveClick: async () => {
      loading.value = true
      try {
        const { deleteRecords } = await import('@/shared/api/common')
        const res = await deleteRecords(entity.value, [name])
        if (res.success) {
          message.success(res.message || t('Deleted successfully'))
          await loadData()
        } else {
          message.error(res.message || t('Delete failed'))
        }
      } catch (error) {
        message.error(t('Delete failed'))
        console.error('Delete error:', error)
      } finally {
        loading.value = false
      }
    }
  })
}


function isBooleanField(fieldName: string) {
  // 通过元数据检测布尔字段
  const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
  if (fieldMeta) {
    // 检查字段类型
    if (fieldMeta.fieldtype === 'Check') return true
    
    // 检查是否有一个布尔值字段的特征（值为0/1）
    // 或者通过字段名包含布尔关键字检测
    const boolKeywords = ['enabled', 'disabled', 'active', 'status']
    return boolKeywords.some(keyword => fieldName.toLowerCase().includes(keyword))
  }
  return false
}

// 检查是否为Select类型字段
function isSelectField(fieldName: string) {
  const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
  return fieldMeta?.fieldtype === 'Select'
}

// 检查是否为Icon类型字段
function isIconField(fieldName: string) {
  const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
  return fieldMeta?.fieldtype === 'Icon'
}

// Select字段颜色配置映射（柔和、低饱和度）
// 格式：{ fieldName: { value: color } } 或 { 'global': { value: color } } 用于所有Select字段
// 推荐使用柔和颜色，如：'#e0f2fe'（浅蓝）、'#dcfce7'（浅绿）等
const selectFieldColors = ref<Record<string, Record<string, string>>>({
  // 全局默认颜色映射（适用于所有Select字段，可被字段特定配置覆盖）
  'global': {
    // 可以根据需要添加默认颜色（使用柔和色调）
  }
})

// Select字段文字颜色配置映射（与背景色配对）
// 格式与 selectFieldColors 相同，但存储的是文字颜色
const selectFieldTextColors = ref<Record<string, Record<string, string>>>({
  'global': {}
})

// 获取Select字段值的背景色
function getSelectBadgeColor(fieldName: string, value: any): string {
  if (!value || value === '') return ''
  
  const valueStr = String(value)
  
  // 1. 先检查字段特定的颜色配置
  if (selectFieldColors.value[fieldName] && selectFieldColors.value[fieldName][valueStr]) {
    return selectFieldColors.value[fieldName][valueStr]
  }
  
  // 2. 检查全局颜色配置
  if (selectFieldColors.value['global'] && selectFieldColors.value['global'][valueStr]) {
    return selectFieldColors.value['global'][valueStr]
  }
  
  // 3. 使用基于值的哈希生成默认颜色（保证同一值始终显示相同颜色）
  return getDefaultColorForValue(valueStr)
}

// 根据值生成默认颜色（使用哈希算法确保一致性）
// 使用柔和、低饱和度的现代色彩方案，适合长时间观看
function getDefaultColorForValue(value: string): string {
  // 柔和、低饱和度的现代色彩方案（背景色 + 文字色配置）
  const colors = [
  { bg: '#e6f8f0', text: '#0d684b' }, // 主品牌青绿
  { bg: '#dcfce7', text: '#166534' }, // 绿
  { bg: '#e0f2fe', text: '#0369a1' }, // 蓝
  { bg: '#fef9c3', text: '#713f12' }, // 柔黄
  { bg: '#fee2e2', text: '#991b1b' }, // 红
  { bg: '#fdf2f8', text: '#9d174d' }, // 粉
  { bg: '#f5f3ff', text: '#6d28d9' }, // 紫
  { bg: '#fff7ed', text: '#9a3412' }, // 橙
  { bg: '#f0fdfa', text: '#115e59' }, // 深青绿（呼应主色）
  { bg: '#f1f5f9', text: '#0f172a' }, // 中性灰
];
  
  // 简单的哈希函数
  let hash = 0
  for (let i = 0; i < value.length; i++) {
    hash = ((hash << 5) - hash) + value.charCodeAt(i)
    hash = hash & hash // 转换为32位整数
  }
  
  const colorConfig = colors[Math.abs(hash) % colors.length]
  // 存储文字颜色到数据中，用于动态设置
  return colorConfig.bg
}

// 获取Select字段值的文字颜色（与背景色配对）
function getSelectBadgeTextColor(fieldName: string, value: any): string {
  if (!value || value === '') return '#374151'
  
  const valueStr = String(value)
  
  // 1. 先检查字段特定的文字颜色配置
  if (selectFieldTextColors.value[fieldName] && selectFieldTextColors.value[fieldName][valueStr]) {
    return selectFieldTextColors.value[fieldName][valueStr]
  }
  
  // 2. 检查全局文字颜色配置
  if (selectFieldTextColors.value['global'] && selectFieldTextColors.value['global'][valueStr]) {
    return selectFieldTextColors.value['global'][valueStr]
  }
  
  // 3. 使用默认文字颜色（基于哈希，与背景色配对）
  const textColors = [
    '#0369a1', '#166534', '#92400e', '#991b1b', '#6b21a8',
    '#9f1239', '#0e7490', '#15803d', '#9a3412', '#4338ca'
  ]
  
  let hash = 0
  for (let i = 0; i < valueStr.length; i++) {
    hash = ((hash << 5) - hash) + valueStr.charCodeAt(i)
    hash = hash & hash
  }
  
  return textColors[Math.abs(hash) % textColors.length]
}

function formatDisplayValue(value: any, fieldName: string, row?: any) {
  let result: any = value
  
  // 获取字段元数据
  const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
  
  // 特殊处理：modified 和 creation 字段显示格式化日期时间
  if (fieldName === 'modified' || fieldName === 'creation') {
    return formatDateTime(value)
  }
  
  // 对齐旧版list_view.js：Link字段根据linkFieldTitleFields决定显示name还是title
  if (fieldMeta && fieldMeta.fieldtype === 'Link' && fieldMeta.options && value) {
    const titleFieldName = linkFieldTitleFields.value[fieldName]
    if (titleFieldName) {
      // 启用了show_title_field_in_link：优先显示JOIN回来的标题值
      // 行数据中包含 customer_customer_name 这样的字段
      result = row?.[`${fieldName}_${titleFieldName}`] || t_ctx(value)
    } else {
      // 未启用show_title_field_in_link或title_field为name：显示name值
      result = t_ctx(value)
    }
  } else if (fieldMeta && fieldMeta.options) {
    // 尝试从字段元数据获取翻译选项（非Link字段）
    const options = fieldMeta.options.split('\n').filter((s: string) => s.trim() !== '')
    if (options.includes(value)) {
      result = t_ctx(value)
    }
  } else if (typeof value === 'string' && value.length > 0) {
    result = t_ctx(value)
  }
  
  return result
}

// Format datetime (aligned with default.vue and user.vue)
function formatDateTime(value: any) {
  if (!value) return '—'
  try {
    return formatDateTimeInTimezone(value)
  } catch {
    return String(value)
  }
}
</script>

<style scoped>
.page { 
  padding: 16px; 
  width: 100%;
  min-height: 100vh;
}

.page-header {
  display: flex;
  align-items: flex-start; 
  justify-content: space-between;
  margin-bottom: 24px;
}

.header-left h2 { font-size: 28px; font-weight: 700; color: #1f2937; margin: 0; }

/* Filter bar container */
.filter-bar-container {
  margin-bottom: 12px;
}


.agent-list { background: white; border: 1px solid #e5e7eb; border-radius: 12px; overflow: hidden; }
.list-pagination { padding: 16px 20px; border-top: 1px solid #e5e7eb; background: #f9fafb; display: flex; justify-content: center; }

/* 列表内容包装器 */
.list-content-wrapper {
  position: relative;
}

.list-content-wrapper.loading-state {
  opacity: 0.7;
  pointer-events: none;
}

/* 首次加载时显示全屏加载 */
.loading-full {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  color: #6b7280;
  font-size: 16px;
}

.loading-full i {
  margin-right: 8px;
}

/* 已有数据时的轻微加载指示（右上角浮动） */
.loading-overlay {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 50%;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  color: #3b82f6;
  font-size: 14px;
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.7;
  }
}

/* 卡片视图样式（对齐 AgentList 设计） */
.agent-grid { 
  display: grid; 
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); 
  gap: 20px; 
  margin-bottom: 24px; 
}

.agent-card { 
  background: white; 
  border: 1px solid #e5e7eb; 
  border-radius: 12px; 
  padding: 0;
  cursor: pointer; 
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); 
  position: relative; 
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 100%;
  content-visibility: auto;
  contain-intrinsic-size: 0 280px;
}

.agent-card:hover {
  border-color: #2563eb; 
  border-width: 2px;
}

.agent-card.selected { 
  border-color: #3b82f6; 
  background: #f0f9ff; 
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); 
}

.card-checkbox { 
  position: absolute; 
  top: 12px; 
  right: 12px; 
  z-index: 10; 
}

.card-checkbox input[type="checkbox"] { 
  cursor: pointer; 
  accent-color: #3b82f6; 
  width: 18px;
  height: 18px;
}

.card-image {
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.card-image::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.02) 100%);
  pointer-events: none;
}

.card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  will-change: transform;
  transform: translateZ(0);
}

.agent-card:hover .card-image img {
  transform: scale(1.02) translateZ(0);
}

.card-content { 
  display: flex; 
  flex-direction: column; 
  flex: 1;
  padding: 20px;
  padding-bottom: 12px;
  min-height: 0;
}

.info { 
  display: flex; 
  flex-direction: column; 
  gap: 10px; 
  flex: 1;
  min-width: 0;
  width: 100%;
  overflow: hidden;
}

.title { 
  font-size: 16px; 
  font-weight: 600; 
  color: #111827; 
  line-height: 1.4; 
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.desc { 
  font-size: 13px; 
  color: #6b7280; 
  line-height: 1.5; 
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.meta { 
  display: flex; 
  align-items: center; 
  gap: 6px; 
  flex-wrap: wrap; 
  margin-top: 4px;
  width: 100%;
  overflow: hidden;
}

.badge { 
  background: #f3f4f6; 
  color: #374151; 
  padding: 4px 10px; 
  border-radius: 6px; 
  font-size: 12px; 
  font-weight: 500;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  display: inline-block;
  min-width: 0;
}

/* Select字段Badge样式 - 柔和现代风格 */
.select-badge {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 16px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  line-height: 1.5;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  border: 1px solid rgba(0, 0, 0, 0.06);
  backdrop-filter: blur(4px);
}

.select-badge:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* 工具栏容器样式（保留用于布局） */
.header-right { display: flex; align-items: center; gap: 12px; }

/* 注意：操作列的样式现在由 DefaultListActions 组件和自定义操作组件自己管理 */
/* 父组件不再定义 card-actions 和 col-actions 样式，符合组件自包含的最佳实践 */

/* 列表样式 - 与 AgentList 完全一致 */
.col-checkbox {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
}

.list-header {
  display: grid;
  align-items: center;
  gap: 16px;
  padding: 16px 20px;
  background: #f9fafb;
  border-bottom: 1px solid #e5e7eb;
  font-size: 14px;
  font-weight: 600;
  color: #374151;
}


.list-item {
  display: grid;
  align-items: center;
  gap: 16px;
  padding: 16px 20px;
  border-bottom: 1px solid #f3f4f6;
  cursor: pointer;
  transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  content-visibility: auto;
  contain-intrinsic-size: 0 70px;
}

.list-item:hover {
  background: #f9fafb;
}

.list-item:last-child {
  border-bottom: none;
}

.list-item.selected {
  background: #f0f9ff;
  border-color: #3b82f6;
}

/* 无权限记录样式 */
.list-item.no-permission {
  opacity: 0.5;
  cursor: not-allowed;
  background: #f9fafb;
}

.list-item.no-permission:hover {
  background: #f9fafb;
}

.agent-card.no-permission {
  opacity: 0.5;
  cursor: not-allowed;
}

.col-image {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  flex-shrink: 0;
}

.col-image img {
  width: 50px;
  height: 50px;
  object-fit: cover;
  object-position: center;
  border-radius: 8px;
  border: 1px solid #e5e7eb;
  background: #f9fafb;
  will-change: transform;
  transform: translateZ(0);
  image-rendering: -webkit-optimize-contrast;
}

.list-item:hover .col-image img {
  border-color: #3b82f6;
  border-width: 2px;
}

.col-image .image-placeholder {
  color: #9ca3af;
  font-size: 14px;
}

/* 操作列容器样式（用于网格布局，按钮样式由 DefaultListActions 组件处理） */
.col-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

/* 布尔值样式 */
.boolean-true {
  color: #059669;
  font-weight: bold;
  font-size: 16px;
}

.boolean-false {
  color: #9ca3af;
  font-weight: bold;
  font-size: 16px;
}

/* Icon 字段图标样式 - 灰色系 */
.icon-gray {
  color: #9ca3af;
}

/* 列表列通用样式 - 确保溢出省略号截断 */
.list-header > div:not(.col-checkbox),
.list-item > div:not(.col-checkbox):not(.col-actions) {
  min-height: 24px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0; /* 关键：允许 grid 子项收缩至0，使 ellipsis 生效 */
  line-height: 24px; /* 配合 min-height 实现垂直居中 */
}

/* hide_id_in_list 时 name 列折叠 */
.col-collapsed {
  padding: 0 !important;
  overflow: hidden !important;
  min-width: 0 !important;
  border: none !important;
}

/* 列表头列额外样式 - 标题不截断，仅对齐布局 */
.list-header > div:not(.col-checkbox):not(.col-actions) {
  overflow: visible;
  text-overflow: unset;
  white-space: normal;
}

/* 列表行数据列 */
.list-item > div:not(.col-checkbox):not(.col-actions) {
  cursor: pointer;
}

</style>


