<template>
  <div class="generic-detail-page">
    <!-- 页面头部 -->
    <div class="page-header">
      <n-space justify="space-between" align="center">
        <div>
          <h1 class="page-title">{{ pageTitle }}</h1>
          <p class="page-description">{{ pageDescription }}</p>
        </div>
        <component
          v-if="toolbarComponent"
          :is="toolbarComponent"
          :context="{
            entity,
            id,
            record,
            canEdit,
            canDelete,
            loading,
            save: handleSave,
            submit: handleSubmit,
            cancel: handleCancelPg,
            refresh: handleRefresh,
            delete: handleDelete,
            goBack: goBack,
            toggleSidebarPosition: toggleSidebarPosition,
            sidebarPosition,
            isSubmittable: isSubmittable,
            pageStatus: pageStatus,
            pageMeta: pageMeta,
            rename: handleRename,
            duplicate: handleDuplicate,
            router,
            t: t_ctx
          }"
          :entity="entity"
          :id="id"
          :record="record"
          :can-edit="canEdit"
          :can-delete="canDelete"
          :loading="loading"
          :is-submittable="isSubmittable"
          :page-status="pageStatus"
          :sidebar-position="sidebarPosition"
          :page-meta="pageMeta"
          @toggle-sidebar-position="toggleSidebarPosition"
          @refresh="handleRefresh"
          @delete="handleDelete"
          @go-back="goBack"
          @save="handleSave"
          @submit="handleSubmit"
          @cancel-pg="handleCancelPg"
          @rename="handleRename"
          @duplicate="handleDuplicate"
        />
        <DefaultToolbar
          v-else
          :entity="entity"
          :id="id"
          :record="record"
          :can-edit="canEdit"
          :can-delete="canDelete"
          :loading="loading"
          :is-submittable="isSubmittable"
          :page-status="pageStatus"
          :sidebar-position="sidebarPosition"
          :page-meta="pageMeta"
          @toggle-sidebar-position="toggleSidebarPosition"
          @refresh="handleRefresh"
          @delete="handleDelete"
          @go-back="goBack"
          @save="handleSave"
          @submit="handleSubmit"
          @cancel-pg="handleCancelPg"
          @rename="handleRename"
          @duplicate="handleDuplicate"
        />
      </n-space>
    </div>

    <!-- 初次加载状态 -->
    <div v-if="initialLoading" class="loading-container">
      <div class="loading-spinner"></div>
    </div>

    <!-- PageType non-dev readonly alert -->
    <n-alert v-if="isPageTypeReadonly && !initialLoading" type="warning" :bordered="false" style="margin: 12px 16px 0">
      {{ t('This is a standard PageType and can not be modified directly.') }}
      <router-link to="/app/customize-form">{{ t('Use Customize Form') }}</router-link>
    </n-alert>

    <!-- 主布局容器 - 初次加载后始终显示，切换时不隐藏 -->
    <n-layout v-if="!initialLoading" class="detail-page-layout" :has-sider="true">
      <!-- 左侧边栏 -->
      <n-layout-sider 
        v-if="sidebarPosition === 'left'"
        :width="'25%'"
        :collapsed="actualSidebarCollapsed"
        :collapsed-width="0"
        :show-trigger="false"
        :collapsible="true"
        :responsive="true"
        :breakpoint="768"
      >
        <FormPanel 
          :position="sidebarPosition"
          :collapsed="actualSidebarCollapsed"
          :has-content="sidebarHasContent"
          @toggle-collapse="toggleSidebarCollapse"
        >
          <ImageSection 
            :meta-fields="metaFields"
            :record="record"
            :page-meta="pageMeta"
            :can-edit="canEdit"
            :entity="entity"
            :id="id"
            @open-gallery="(url) => attachmentSectionRef?.openByUrl(url)"
            @refresh="loadDetail"
          />
          <AttachmentSection 
            ref="attachmentSectionRef"
            :meta-fields="metaFields"
            :record="record"
            :can-edit="canEdit"
            @add-attachment="handleAddAttachment"
            @attachment-uploaded="loadDetail"
            @delete-attachment="handleDeleteAttachment"
          />
          <TagSection 
            :meta-fields="metaFields"
            :record="record"
          />
        </FormPanel>
      </n-layout-sider>

      <!-- 主内容区域 -->
      <n-layout-content>
        <!-- 控制按钮 - 左侧边栏 -->
         <div 
           v-if="sidebarPosition === 'left'" 
           class="sidebar-toggle-btn toggle-left"
         >
           <n-button 
             type="default" 
             size="small" 
             circle
             @click="toggleSidebarCollapse"
             :title="actualSidebarCollapsed ? '展开侧边栏' : '收起侧边栏'"
             class="toggle-button"
           >
             <template #icon>
               <n-icon>
                 <Icon :icon="actualSidebarCollapsed ? 'tabler:chevron-left' : 'tabler:chevron-right'" />
               </n-icon>
             </template>
           </n-button>
         </div>
         
         <!-- 控制按钮 - 右侧边栏 -->
         <div 
           v-if="sidebarPosition === 'right'" 
           class="sidebar-toggle-btn toggle-right"
         >
           <n-button 
             type="default" 
             size="small" 
             circle
             @click="toggleSidebarCollapse"
             :title="actualSidebarCollapsed ? '展开侧边栏' : '收起侧边栏'"
             class="toggle-button"
           >
             <template #icon>
               <n-icon>
                 <Icon :icon="actualSidebarCollapsed ? 'tabler:chevron-right' : 'tabler:chevron-left'" />
               </n-icon>
             </template>
           </n-button>
         </div>
        <!-- 表单内容 - 按照 jingrow 方式渲染 -->
        <div class="form-layout">
          <div class="form-page">
        <!-- 标签页 -->
        <div v-if="hasTabs" class="form-tabs-list">
          <ul class="nav form-tabs">
            <li 
              v-for="tab in tabs" 
              :key="tab.key"
              class="nav-item"
              @click="activeTab = tab.key"
            >
              <a 
                :class="['nav-link', { active: activeTab === tab.key }]"
                href="#"
              >
                {{ t(tab.label) }}
              </a>
            </li>
          </ul>
        </div>

        <!-- 标签内容 -->
        <div class="form-tab-content">
          <div 
            v-for="tab in tabs" 
            :key="tab.key"
            :class="['tab-pane', { active: activeTab === tab.key }]"
          >
            <div class="form-sections">
              <!-- 渲染每个 Section -->
              <div v-for="section in getTabSections(tab)" :key="section.key" class="form-section">
                <!-- 可折叠的 Section -->
                <n-collapse v-if="section.collapsible && section.label">
                  <n-collapse-item :title="t(section.label)" :name="section.key">
                    <div class="section-body">
                      <!-- 渲染每个 Column -->
                      <div 
                        v-for="column in section.columns" 
                        :key="column.key" 
                        class="form-column"
                      >
                            <!-- Column 字段 -->
                            <FieldRenderer 
                              v-for="field in column.fields" 
                              :key="field.fieldname"
                              :df="field"
                              :record="record"
                              :canEdit="canEdit"
                              :ctx="{ t: t_ctx, getSelectOptions, toDateValue, updateDateValue, handleButtonClick, getJsonDisplayValue, updateJsonValue, formatJson, entity: entity, id: id, reload: async () => { await loadDetail() }, save: handleSave, saveSilent: () => handleSave({ silent: true }), seenByExpanded, toggleSeenBy, seenByUsers, onFieldChange }"
                              v-show="shouldShowField(field)"
                            />
                      </div>
                    </div>
                  </n-collapse-item>
                </n-collapse>
                
                <!-- 不可折叠的 Section -->
                <template v-else>
                  <!-- Section 标题 -->
                  <div v-if="section.label" class="section-header">
                    <h4>{{ t(section.label) }}</h4>
                  </div>
                  
                  <!-- Section 内容 -->
                  <div class="section-body">
                    <!-- 渲染每个 Column -->
                    <div 
                      v-for="column in section.columns" 
                      :key="column.key" 
                      class="form-column"
                    >
                          <!-- Column 字段 -->
                          <FieldRenderer 
                            v-for="field in column.fields" 
                            :key="field.fieldname"
                            :df="field"
                            :record="record"
                            :canEdit="canEdit"
                            :ctx="{ t: t_ctx, getSelectOptions, toDateValue, updateDateValue, handleButtonClick, getJsonDisplayValue, updateJsonValue, formatJson, entity: entity, id: id, reload: async () => { await loadDetail() }, save: handleSave, saveSilent: () => handleSave({ silent: true }), seenByExpanded, toggleSeenBy, seenByUsers, onFieldChange }"
                            v-show="shouldShowField(field)"
                          />
                    </div>
                  </div>
                </template>
              </div>
            </div>
          </div>
        </div>
      </div>
      </div>
      <!-- Activity Section: Like + Comment + Timeline -->
      <ActivitySection
        ref="activitySectionRef"
        :entity="entity"
        :id="id"
        :record="record"
        :can-edit="canEdit"
        @refresh="loadDetail"
      />
      <!-- 统一的系统信息页脚 -->
      <div class="meta-footer">
        <div class="meta-item">
          <span class="meta-label">{{ t('Modified By') }}</span>
          <span class="meta-value">{{ record.modified_by || '—' }}</span>
        </div>
        <div class="meta-sep"></div>
        <div class="meta-item">
          <span class="meta-label">{{ t('Modified At') }}</span>
          <span class="meta-value">{{ formatDateTime(record.modified) }}</span>
        </div>
      </div>
      </n-layout-content>
      
      <!-- 右侧边栏 -->
      <n-layout-sider 
        v-if="sidebarPosition === 'right'"
        :width="'25%'"
        :collapsed="actualSidebarCollapsed"
        :collapsed-width="0"
        :show-trigger="false"
        :collapsible="true"
        :responsive="true"
        :breakpoint="768"
        placement="right"
      >
        <FormPanel 
          :position="sidebarPosition"
          :collapsed="actualSidebarCollapsed"
          :has-content="sidebarHasContent"
          @toggle-collapse="toggleSidebarCollapse"
        >
          <ImageSection 
            :meta-fields="metaFields"
            :record="record"
            :page-meta="pageMeta"
            :can-edit="canEdit"
            :entity="entity"
            :id="id"
            @open-gallery="(url) => attachmentSectionRef?.openByUrl(url)"
            @refresh="loadDetail"
          />
          <AttachmentSection 
            ref="attachmentSectionRef"
            :meta-fields="metaFields"
            :record="record"
            :can-edit="canEdit"
            @add-attachment="handleAddAttachment"
            @attachment-uploaded="loadDetail"
            @delete-attachment="handleDeleteAttachment"
          />
          <TagSection 
            :meta-fields="metaFields"
            :record="record"
          />
        </FormPanel>
      </n-layout-sider>
    </n-layout>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref, shallowRef, markRaw, computed, watch, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NButton, NSpace, NIcon, NAlert, useMessage, useDialog, NLayout, NLayoutSider, NLayoutContent, NCollapse, NCollapseItem } from 'naive-ui'
import FieldRenderer from '@/core/pagetype/form/FieldRenderer.vue'
import ActivitySection from '@/core/pagetype/form/panel/ActivitySection.vue'
import { Icon } from '@iconify/vue'
import { resolveSidebarPanel } from '@/core/registry/sidebarOverride'
import { defineAsyncComponent } from 'vue'
const FormPanel = defineAsyncComponent(async () => {
  const mod = await resolveSidebarPanel(entity.value, 'FormPanel.vue')
  return mod || (await import('@/core/pagetype/form/panel/FormPanel.vue'))
})
const ImageSection = defineAsyncComponent(async () => {
  const mod = await resolveSidebarPanel(entity.value, 'ImageSection.vue')
  return mod || (await import('@/core/pagetype/form/panel/ImageSection.vue'))
})
const AttachmentSection = defineAsyncComponent(async () => {
  const mod = await resolveSidebarPanel(entity.value, 'AttachmentSection.vue')
  return mod || (await import('@/core/pagetype/form/panel/AttachmentSection.vue'))
})
const TagSection = defineAsyncComponent(async () => {
  const mod = await resolveSidebarPanel(entity.value, 'TagSection.vue')
  return mod || (await import('@/core/pagetype/form/panel/TagSection.vue'))
})
import axios from 'axios'
import { t, createT } from '@/shared/i18n'
import { formatDateTimeInTimezone } from '@/shared/utils/timezone'
import { updateRecord, getRecord, getRecordAttachments, deleteAttachment, uploadAttachment, deleteRecords, getPageTypeMeta, api } from '@/shared/api/common'
import { usePageTypeSlug } from '@/shared/utils/slug'
import { resolvePagetypeToolbarOverride } from '@/core/registry/pagetypeOverride'
import DefaultToolbar from '@/core/pagetype/default_toolbar.vue'
import { usePermissionStore } from '@/shared/stores/permissions'
import { useAuthStore } from '@/shared/stores/auth'
import { createFieldChangeTrigger, triggerRecordInit } from '@/core/plugins/fieldPlugin'
import { loadAllPlugins } from '@/core/plugins/pluginLoader'
import { useRealtime, type PgUpdateData } from '@/shared/composables/useRealtime'

const route = useRoute()
const router = useRouter()
const message = useMessage()
const dialog = useDialog()
const permissionStore = usePermissionStore()
const authStore = useAuthStore()
const attachmentSectionRef = ref()
const activitySectionRef = ref()

// 使用组合式函数处理URL slug
const { pagetypeSlug, entity } = usePageTypeSlug(route)

// Context-aware translation: auto-injects entity as msgctxt for all field labels/values
const t_ctx = createT(() => entity.value)

// 覆盖组件引用（工具栏覆盖，整体覆盖由 DetailPage.vue 处理）
const toolbarComponent = shallowRef<any | null>(null)
const id = computed(() => route.params.id as string)
const isNew = computed(() => {
  const idValue = id.value
  return idValue === 'new' || idValue.startsWith('new-')
})
const canEdit = ref(false)
const canDelete = ref(false)
const canRead = computed(() => permissionStore.canRead(entity.value))

const record = reactive<Record<string, any>>({})
const originalRecord = ref<any>({})
const metaFields = ref<any[]>([])
const pageMeta = ref<any>({})
const activeTab = ref('default')
const loading = ref(false)
const initialLoading = ref(true)

// 基于记录行级权限更新 canEdit/canDelete（后端 _can_write/_can_delete 已根据 if_owner 等约束计算）
watch(() => [record._can_write, record._can_delete] as const, ([writeVal, deleteVal]) => {
  if (isNew.value) return // 新记录的 canEdit 由 permissionStore.canWrite 控制
  canEdit.value = writeVal === 1
  canDelete.value = deleteVal === 1
})

const isSubmittable = computed(() => !!pageMeta.value?.is_submittable)
const pageStatus = computed(() => record.pagestatus ?? record.pagestatus ?? -1) // 区分初次加载和记录切换

const isDeveloperMode = computed(() => !!(window as any).jingrow?.boot?.developer_mode)
const isPageTypeReadonly = computed(() => {
  return entity.value === 'PageType' && !isNew.value && !isDeveloperMode.value && !record.custom
})

// Field change plugin trigger
const onFieldChange = createFieldChangeTrigger(entity.value, record)

const pageTitle = computed(() => {
  if (isNew.value) {
    return t('Create') + ' ' + t(entity.value)
  }
  return record.name || record.label || (id.value !== 'new' ? id.value : t(entity.value))
})

const pageDescription = computed(() => {
  if (isNew.value) {
    return t('Create a new record')
  }
  return ''
})

// 计算侧边栏是否有内容
const sidebarHasContent = computed(() => {
  // 检查图片字段 - 基于 pageMeta.image_field 配置
  const hasImages = (() => {
    const imageFieldName = pageMeta.value?.image_field
    if (!imageFieldName || !imageFieldName.trim()) {
      return false
    }
    const fieldValue = record[imageFieldName]
    return Boolean(fieldValue && fieldValue.trim())
  })()
  
  // 检查附件（包括图片附件）
  const hasAttachments = record.attachments && record.attachments.length > 0
  
  // 检查标签字段
  const hasTags = (() => {
    const userTags = record._user_tags
    if (userTags && typeof userTags === 'string') {
      const trimmed = userTags.trim()
      if (trimmed) {
        return trimmed.split(',').some(tag => tag.trim().length > 0)
      }
    }
    return false
  })()
  
  return hasImages || hasAttachments || hasTags
})

const tabs = computed(() => {
  const orderedFields = getOrderedFields()
  
  const result: any[] = []
  let currentTab: any = null
  let currentSection: any = null
  let currentColumn: any = null
  
  // 检查是否有 Tab Break 字段
  const hasTabBreak = orderedFields.some(field => field.fieldtype === 'Tab Break')
  
  if (!hasTabBreak) {
    currentTab = {
      key: 'default',
      label: t('Detail'),
      sections: []
    }
  }
  
  for (const field of orderedFields) {
    
    switch (field.fieldtype) {
      case 'Tab Break':
        
        // 保存当前 Tab（如果有的话）
        if (currentTab) {
          // 保存当前 Section（如果有的话）
          if (currentSection) {
            // 保存当前 Column（如果有的话）
            if (currentColumn && currentColumn.fields.length > 0) {
              if (!currentSection.columns) currentSection.columns = []
              currentSection.columns.push({ ...currentColumn })
            }
            // 保存 Section
            if (currentSection.columns && currentSection.columns.length > 0) {
              if (!currentTab.sections) currentTab.sections = []
              currentTab.sections.push({ ...currentSection })
            }
          }
          // 保存 Tab
          if (currentTab.sections && currentTab.sections.length > 0) {
            result.push({ ...currentTab })
          }
        }
        
        // 开始新 Tab
        currentTab = {
          key: field.fieldname || field.label || `tab_${result.length + 1}`,
          label: field.label || field.fieldname || t('Detail'),
          sections: []
        }
        currentSection = null
        currentColumn = null
        break
        
      case 'Section Break':
        
        // 如果 Section Break 是 hidden 的，跳过不创建新 section
        if (field.hidden === 1 || field.hidden === true || field.hidden === '1') {
          break
        }
        
        // 保存当前 Section（如果有的话）
        if (currentSection) {
          // 保存当前 Column（如果有的话）
          if (currentColumn && currentColumn.fields.length > 0) {
            if (!currentSection.columns) currentSection.columns = []
            currentSection.columns.push({ ...currentColumn })
          }
          // 保存 Section
          if (currentSection.columns && currentSection.columns.length > 0) {
            if (!currentTab.sections) currentTab.sections = []
            currentTab.sections.push({ ...currentSection })
          }
        }
        
        // 开始新 Section，支持 collapsible 属性
        currentSection = {
          key: field.fieldname || field.label || `section_${currentTab ? currentTab.sections.length + 1 : 1}`,
          label: field.label || '',
          columns: [],
          collapsible: field.collapsible === 1 || field.collapsible === true,
          collapsed: false
        }
        currentColumn = null
        break
        
      case 'Column Break':
        
        // 确保有 Tab 和 Section
        if (!currentTab) {
          currentTab = {
            key: 'default',
            label: t('Detail'),
            sections: []
          }
        }
        if (!currentSection) {
          currentSection = {
            key: 'default',
            label: '',
            columns: []
          }
        }
        
        // 保存当前 Column（如果有的话）
        if (currentColumn && currentColumn.fields.length > 0) {
          if (!currentSection.columns) currentSection.columns = []
          currentSection.columns.push({ ...currentColumn })
        }
        
        // 开始新 Column
        currentColumn = {
          key: `column_${currentSection.columns ? currentSection.columns.length : 0}`,
          fields: []
        }
        break
        
      default:
        // 普通字段
        // 确保有 Tab、Section 和 Column
        if (!currentTab) {
          currentTab = {
            key: 'default',
            label: t('Detail'),
            sections: []
          }
        }
        if (!currentSection) {
          currentSection = {
            key: 'default',
            label: '',
            columns: []
          }
        }
        if (!currentColumn) {
          currentColumn = {
            key: 'default',
            fields: []
          }
        }
        
        currentColumn.fields.push(field)
        break
    }
  }
  
  // 保存最后的 Tab、Section 和 Column
  if (currentTab) {
    if (currentSection) {
      if (currentColumn && currentColumn.fields.length > 0) {
        if (!currentSection.columns) currentSection.columns = []
        currentSection.columns.push({ ...currentColumn })
      }
      if (currentSection.columns && currentSection.columns.length > 0) {
        if (!currentTab.sections) currentTab.sections = []
        currentTab.sections.push({ ...currentSection })
      }
    }
    if (currentTab.sections && currentTab.sections.length > 0) {
      result.push({ ...currentTab })
    }
  }
  
  return result
})

const hasTabs = computed(() => tabs.value.length > 1)

// 按照 field_order 获取有序字段
function getOrderedFields() {
  const fieldsMap = new Map()
  metaFields.value.forEach(field => {
    fieldsMap.set(field.fieldname, field)
  })
  
  let orderedFields: any[] = []
  
  if (isNew.value && (pageMeta.value.autoname === "Prompt" || pageMeta.value.autoname?.startsWith("prompt"))) {
    const newnameField = {
      fieldname: "__newname",
      fieldtype: "Data",
      label: "Name",
      reqd: 1,
      placeholder: "Enter document name"
    }
    orderedFields.push(newnameField)
  }
  
  // 按照 pageMeta.field_order 排序
  if (pageMeta.value.field_order && Array.isArray(pageMeta.value.field_order)) {
    const ordered = pageMeta.value.field_order
      .filter((fieldname: string) => fieldsMap.has(fieldname))
      .map((fieldname: string) => fieldsMap.get(fieldname))
    
    // 添加不在 field_order 中的字段
    const orderedFieldnames = new Set(pageMeta.value.field_order)
    const remaining = metaFields.value.filter(f => !orderedFieldnames.has(f.fieldname))
    
    orderedFields = [...orderedFields, ...ordered, ...remaining]
  } else {
    orderedFields = [...orderedFields, ...metaFields.value]
  }
  
  return orderedFields
}

function getTabSections(tab: any) {
  return tab.sections || []
}

// 动态字段选项缓存
const dynamicFieldOptions = ref<Record<string, string[]>>({})

function getSelectOptions(field: any) {
  // 检查是否有动态加载的选项
  if (dynamicFieldOptions.value[field.fieldname]) {
    const options = dynamicFieldOptions.value[field.fieldname]
    return options.map((opt: string) => ({ label: t_ctx(opt), value: opt }))
  }
  
  // 使用静态选项
  if (!field.options) return []
  const staticOptions = field.options.split('\n').filter((s: string) => s.trim() !== '')
  return staticOptions.map((opt: string) => ({ label: t_ctx(opt), value: opt }))
}

// 折叠状态与映射到徽章的数据
const seenByExpanded = ref(false)
const seenByUsers = computed(() => {
  const list = Array.isArray(record?.seen_by) ? record.seen_by : []
  return list.map((item: any, idx: number) => ({
    key: item.name || item.user || String(idx),
    label: item.user || item.owner || '—'
  }))
})

// 侧边栏状态管理
const sidebarPosition = ref<'left' | 'right'>('left') // 默认左侧
const sidebarCollapsed = ref(true) // 默认收起

// 计算侧边栏是否应该收起
const actualSidebarCollapsed = computed(() => {
  return sidebarCollapsed.value
})

// 从 localStorage 读取用户偏好设置
const loadSidebarPreferences = () => {
  const savedPosition = localStorage.getItem('jingrow-sidebar-position')
  
  if (savedPosition === 'left' || savedPosition === 'right') {
    sidebarPosition.value = savedPosition
  }
}

// 保存用户偏好设置
const saveSidebarPreferences = () => {
  localStorage.setItem('jingrow-sidebar-position', sidebarPosition.value)
}

// 切换侧边栏位置
const toggleSidebarPosition = () => {
  sidebarPosition.value = sidebarPosition.value === 'left' ? 'right' : 'left'
  saveSidebarPreferences()
}

// 监听侧边栏内容变化
watch(sidebarHasContent, (hasContent) => {
  if (hasContent) {
    // 有内容时，自动展开
    sidebarCollapsed.value = false
  }
})

// 切换侧边栏折叠状态
const toggleSidebarCollapse = () => {
  sidebarCollapsed.value = !sidebarCollapsed.value
}

// 添加附件
async function handleAddAttachment() {
  // 创建文件输入元素
  const input = document.createElement('input')
  input.type = 'file'
  input.multiple = true
  input.accept = '*/*'
  
  input.onchange = async (e) => {
    const files = (e.target as HTMLInputElement).files
    if (!files || files.length === 0) return
    
    try {
      // 显示上传进度
      message.loading(t('Uploading attachments...'), { duration: 0 })
      
      // 逐个上传文件
      const uploadPromises = Array.from(files).map(async (file) => {
        const result = await uploadAttachment(file, entity.value, id.value, false)
        if (!result.success) {
          throw new Error(result.message || 'Upload failed')
        }
        return result.data
      })
      
      // 等待所有文件上传完成
      await Promise.all(uploadPromises)
      
      // 关闭加载消息
      message.destroyAll()
      message.success(t('Attachments uploaded successfully'))
      
      // 重新加载附件列表
      await loadDetail()
    } catch (error: any) {
      message.destroyAll()
      message.error(error.message || t('Failed to upload attachment'))
      console.error('Upload error:', error)
    }
  }
  
  input.click()
}

// 删除附件
async function handleDeleteAttachment(attachment: any) {
  try {
    const result = await deleteAttachment(attachment.name)
    if (result.success) {
      message.success(t('Attachment deleted successfully'))
      // 重新加载附件列表
      await loadDetail()
    } else {
      message.error(result.message || t('Failed to delete attachment'))
    }
  } catch (error) {
    message.error(t('Failed to delete attachment'))
    console.error('Delete attachment error:', error)
  }
}

function toggleSeenBy() {
  seenByExpanded.value = !seenByExpanded.value
}

// 按照 jingrow 系统逻辑评估字段依赖条件
function evaluateDependsOn(expression: string) {
  if (!expression) return true

  try {
    if (expression.startsWith('eval:')) {
      const code = expression.substring(5)
      const pg = record
      const evaluator = new Function('pg', `return !!(${code})`)
      return !!evaluator(pg)
    }

    return !!record[expression]
  } catch (_err) {
    if (expression.startsWith('eval:')) return false
    return true
  }
}

// 检查字段是否是结构字段（不需要显示）
function isStructuralField(field: any) {
  const isStructural = ['Tab Break', 'Section Break', 'Column Break'].includes(field.fieldtype)
  if (isStructural) {
  }
  return isStructural
}

// 检查字段是否应该显示
function shouldShowField(field: any) {
  
  // 首先检查是否是结构字段
  if (isStructuralField(field)) {
    return false
  }

  // 隐藏字段（与 jingrow 对齐）：hidden 为 1/true 时不显示
  if (field && (field.hidden === 1 || field.hidden === true || field.hidden === '1')) {
    return false
  }
  
  if (!field.depends_on) {
    return true
  }
  
  const result = evaluateDependsOn(field.depends_on)
  return result
}

// 处理按钮点击
function handleButtonClick(_field: any) {
  // 这里可以添加按钮点击的处理逻辑
}

function formatDateTime(value: any) {
  if (!value) return '—'
  try {
    return formatDateTimeInTimezone(value)
  } catch {
    return String(value)
  }
}

// Naive UI DatePicker 期望 number(timestamp) 或 [number, number]
function toDateValue(v: any): number | null {
  if (!v) return null
  // 若已是数字或 Date
  if (typeof v === 'number') return v
  if (v instanceof Date) return v.getTime()
  // 若是 'YYYY-MM-DD' 或 ISO 字符串
  const parsed = new Date(v)
  if (!isNaN(parsed.getTime())) return parsed.getTime()
  return null
}

function updateDateValue(fieldname: string, v: number | null) {
  if (v === null || v === undefined) {
    record[fieldname] = null
  } else {
    // 存储为 'YYYY-MM-DD' 字符串，兼容后端
    const d = new Date(v)
    const y = d.getFullYear()
    const m = String(d.getMonth() + 1).padStart(2, '0')
    const day = String(d.getDate()).padStart(2, '0')
    record[fieldname] = `${y}-${m}-${day}`
  }
}

function formatJson(value: any) {
  if (!value) return ''
  try {
    return JSON.stringify(value, null, 2)
  } catch {
    return String(value)
  }
}

// 获取 JSON 字段的显示值
function getJsonDisplayValue(value: any) {
  if (!value) return ''
  
  // 如果已经是字符串，直接返回
  if (typeof value === 'string') {
    try {
      // 尝试格式化字符串 JSON
      const parsed = JSON.parse(value)
      return JSON.stringify(parsed, null, 2)
    } catch {
      // 如果不是有效 JSON，返回原字符串
      return value
    }
  }
  
  // 如果是对象，格式化为 JSON 字符串
  try {
    return JSON.stringify(value, null, 2)
  } catch {
    return String(value)
  }
}

// 更新 JSON 字段的值
function updateJsonValue(fieldName: string, value: string) {
  if (!value.trim()) {
    record[fieldName] = null
    return
  }
  
  try {
    // 尝试解析为 JSON 对象
    record[fieldName] = JSON.parse(value)
  } catch {
    // 如果解析失败，保存为字符串
    record[fieldName] = value
  }
}

// 加载元数据
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 || {}

      // 权限：默认读取后端权限，决定是否可编辑
      const pagetypeName = entity.value
      // Virtual PageType should not be editable (db_insert/db_update raise NotImplementedError)
      if (pageMeta.value.is_virtual) {
        canEdit.value = false
        canDelete.value = false
      } else if (isNew.value) {
        canEdit.value = permissionStore.canWrite(pagetypeName)
        canDelete.value = false
      } else {
        // canEdit/canDelete 由 record._can_write/_can_delete watcher 在 loadDetail 后更新
        // 先设为 false，避免加载前误判
        canEdit.value = false
        canDelete.value = false
      }
      
      // 设置默认活动标签：显示第一个标签页
      if (tabs.value.length > 0) {
        activeTab.value = tabs.value[0].key
      }
    } else {
      message.error(result.message || t('Failed to load metadata'))
      console.error('Failed to load metadata:', result.message)
    }
    
  } catch (error) {
    message.error(t('Failed to load metadata'))
    console.error('Failed to load metadata:', error)
  } finally {
    loading.value = false
  }
}

// Set default values from field definitions for new records
function applyDefaultValues() {
  const titleField = pageMeta.value?.title_field

  for (const field of metaFields.value) {
    if (!field.default || field.fieldname === titleField) continue
    if (field.fieldtype === 'Table' || field.fieldtype === 'Table MultiSelect') continue

    const defaultVal = String(field.default)
    let value: any = undefined

    if (defaultVal === '__user' || defaultVal.toLowerCase() === 'user') {
      value = authStore.user?.name || ''
    } else if (defaultVal === 'user_fullname') {
      value = authStore.user?.full_name || ''
    } else if (defaultVal === 'Today') {
      value = new Date().toISOString().split('T')[0]
    } else if (defaultVal.toLowerCase() === 'now') {
      if (field.fieldtype === 'Time') {
        value = new Date().toTimeString().slice(0, 8)
      } else {
        value = new Date().toISOString().slice(0, 19).replace('T', ' ')
      }
    } else if (defaultVal.startsWith(':')) {
      // Dynamic defaults (e.g. ":User") - skip for now, handled by plugins
      continue
    } else if (field.fieldtype === 'Check') {
      value = defaultVal === '1' ? 1 : 0
    } else if (field.fieldtype === 'Select' && defaultVal) {
      // Use the default as-is for Select fields
      value = defaultVal
    } else {
      value = field.default
    }

    if (value !== undefined && record[field.fieldname] === undefined) {
      record[field.fieldname] = value
    }
  }
}

// 为 record 中 undefined 的字段填充 null
function fillNullFieldDefaults(record: Record<string, any>, fields: any[]) {
  for (const field of fields) {
    if (record[field.fieldname] === undefined) {
      record[field.fieldname] = null
    }
  }
}

// 应用字段配置插件
async function applyFieldConfig() {
  const { triggerFieldConfig } = await import('@/core/plugins/fieldPlugin')
  
  for (const field of metaFields.value) {
    if (field.fieldtype === 'Select' || field.fieldtype === 'Autocomplete') {
      const configuredField = await triggerFieldConfig(entity.value, field, record)
      if (configuredField.options && configuredField.options !== field.options) {
        dynamicFieldOptions.value[field.fieldname] = configuredField.options.split('\n').filter((s: string) => s.trim())
      }
    }
  }
}

// 提取图片URL的函数 - 包含附件中的图片
function extractImageUrls(data: any): string[] {
  const urls: string[] = []
  
  // 从HTML字符串中提取图片URL的正则表达式
  const imageUrlRegex = /\/files\/[^"'\s>]+\.(jpg|jpeg|png|gif|webp)/gi
  
  function traverse(obj: any) {
    if (typeof obj === 'string') {
      // 检查是否是直接的相对路径图片URL
      if (obj.startsWith('/files/') && (obj.includes('.jpg') || obj.includes('.jpeg') || obj.includes('.png') || obj.includes('.gif') || obj.includes('.webp'))) {
        urls.push(obj)
      }
      
      // 从HTML字符串中提取图片URL
      const matches = obj.match(imageUrlRegex)
      if (matches) {
        urls.push(...matches)
      }
    } else if (Array.isArray(obj)) {
      obj.forEach(traverse)
    } else if (obj && typeof obj === 'object') {
      Object.values(obj).forEach(traverse)
    }
  }
  
  traverse(data)
  return [...new Set(urls)] // 去重
}

// 从附件中提取图片URL的函数
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function extractAttachmentImageUrls(attachments: any[]): string[] {
  const urls: string[] = []
  
  attachments.forEach(attachment => {
    const fileUrl = attachment.file_url || attachment.url
    const fileName = attachment.file_name || attachment.name
    
    if (fileUrl && fileName) {
      // 检查是否是图片文件
      const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg']
      const isImage = imageExtensions.some(ext => 
        fileUrl.toLowerCase().includes(ext) || 
        fileName.toLowerCase().includes(ext)
      )
      
      if (isImage && fileUrl.startsWith('/files/')) {
        urls.push(fileUrl)
      }
    }
  })
  
  return [...new Set(urls)] // 去重
}

// 加载详情数据 - 优化版本，同步加载附件数据
async function loadDetail() {
  if (isNew.value) {
    Object.keys(record).forEach(k => delete record[k])
    originalRecord.value = {}
    // Set default values from field definitions
    applyDefaultValues()
    // Trigger record init plugins for new records
    await triggerRecordInit(entity.value, record)
    // Apply field config plugins for new records (set default values)
    await applyFieldConfig()
    // Check for duplicate data pre-filled by toolbar's "Duplicate" action
    const storageKey = `duplicate:${entity.value}`
    try {
      const stored = sessionStorage.getItem(storageKey)
      if (stored) {
        sessionStorage.removeItem(storageKey)
        const copyData = JSON.parse(stored)
        // Merge copy data into record (copy fields overwrite defaults)
        Object.assign(record, copyData)
      }
    } catch {}
    return
  }
  
  // 切换记录时不设置 loading 为 true，保持界面显示
  // 只在初次加载时才显示 loading
  const isInitialLoad = initialLoading.value
  if (isInitialLoad) {
    loading.value = true
  }
  
  try {
    // 并行加载记录信息和附件数据
    const [recordRes, attachmentsRes] = await Promise.all([
      getRecord(entity.value, id.value),
      getRecordAttachments(entity.value, id.value)
    ])
    
    if (recordRes.success && recordRes.data) {
Object.keys(record).forEach(k => delete record[k]); Object.assign(record, recordRes.data)
      
      // 后端 as_dict(no_nulls=True) 会省略值为 null 的字段，导致控件保留旧值
      fillNullFieldDefaults(record, metaFields.value)
      
      // 同步设置附件数据
      if (attachmentsRes.success && attachmentsRes.data) {
        record.attachments = attachmentsRes.data
      }
      
      // PageType non-dev readonly: override canEdit after record is loaded
      if (isPageTypeReadonly.value) {
        canEdit.value = false
        canDelete.value = false
      }
      
      // 记录快照用于脏检查
      try {
        originalRecord.value = JSON.parse(JSON.stringify(record))
      } catch {
        originalRecord.value = { ...record }
      }
    } else {
      message.error(recordRes.message || t('Failed to load detail'))
      Object.keys(record).forEach(k => delete record[k])
    }
    
    // Apply field config plugins for all records
    await applyFieldConfig()
    // 刷新活动记录（上传附件/保存等操作后活动记录需同步更新）
    activitySectionRef.value?.loadPageinfo()
  } catch (error) {
    message.error(t('Failed to load detail'))
    console.error('Failed to load detail:', error)
    Object.keys(record).forEach(k => delete record[k])
  } finally {
    if (isInitialLoad) {
      loading.value = false
    }
  }
}

// 保存
async function handleSave(options?: { silent?: boolean }) {
  const silent = options?.silent ?? false
  // 触发自定义事件，通知所有 FormBuilder 同步 fields
  window.dispatchEvent(new CustomEvent('sync-form-builder-fields'))
  
  // 等待一帧，确保 fields 已同步
  await new Promise(resolve => requestAnimationFrame(resolve))
  
  // 脏检查：无改动则不保存
  try {
    if (JSON.stringify(record) === JSON.stringify(originalRecord.value)) {
      message.info('没有改动，无需保存')
      return
    }
  } catch {
  }
  loading.value = true
  isSaving.value = true
  try {
    if (isNew.value) {
      const url = `/api/data/${encodeURIComponent(entity.value)}`
      const recordData = { ...record }
      if (id.value.startsWith('new-')) {
        recordData.__temporary_name = id.value
      }
      const response = await axios.post(url, recordData)
      if (!silent) message.success(t('Created successfully'))
      // 保存成功更新快照
      try { originalRecord.value = JSON.parse(JSON.stringify(record)) } catch { originalRecord.value = { ...record } }
      
      // 获取新创建的记录名称
      const created = response?.data ?? response
      const newName = created?.name 
        ?? created?.data?.name 
        ?? created?.message?.name 
        ?? created?.document?.name
      
      if (newName) {
        // 延迟跳转到新创建的记录详情页
        setTimeout(() => {
          router.push({ name: 'PageTypeDetail', params: { entity: pagetypeSlug.value, id: newName } })
        }, 1500)
      } else {
        // 如果无法获取新记录名称，跳转到列表页
        setTimeout(() => {
          router.push({ name: 'PageTypeList', params: { entity: pagetypeSlug.value } })
        }, 1500)
      }
    } else {
      const oldLanguage = originalRecord.value.language
      
      // 准备发送的数据：如果 fields 是字符串，解析为数组（Jingrow API 要求）
      const dataToSend = { ...record }
      if (typeof dataToSend.fields === 'string') {
        try {
          dataToSend.fields = JSON.parse(dataToSend.fields)
        } catch (e) {
          console.error('Failed to parse fields:', e)
        }
      }
      
      const res = await updateRecord(entity.value, id.value, dataToSend)
      if (res.success) {
        if (!silent) message.success(t('Saved successfully'))
              
        if (entity.value === 'User' && 
            record.name === authStore.user?.name &&
            record.language &&
            record.language !== oldLanguage) {
          window.location.reload()
          return
        }
              
        // 保存成功更新快照
        try { originalRecord.value = JSON.parse(JSON.stringify(record)) } catch { originalRecord.value = { ...record } }
        // 刷新数据（isSaving 在 loadDetail 期间保持 true，防止自触发 pg_update 重复刷新）
        await loadDetail()
        isSaving.value = false
      } else {
        message.error(res.message || t('Save failed'))
        isSaving.value = false
      }
    }
  } catch (error) {
    message.error(t('Save failed'))
    console.error('Save failed:', error)
    isSaving.value = false
  } finally {
    loading.value = false
  }
}

async function handleSubmit() {
  if (isNew.value || !isSubmittable.value) return
  loading.value = true
  try {
    await api.call('jingrow.client.submit', {
      pg: JSON.stringify(record)
    })
    message.success(t('Submitted'))
    await loadDetail()
  } catch (error: any) {
    message.error(error?.message || t('Submit failed'))
    console.error('Submit failed:', error)
  } finally {
    loading.value = false
  }
}

async function handleCancelPg() {
  if (isNew.value || !isSubmittable.value) return
  loading.value = true
  try {
    await api.call('jingrow.client.cancel', {
      pagetype: entity.value,
      name: id.value
    })
    message.success(t('Cancelled'))
    await loadDetail()
  } catch (error: any) {
    message.error(error?.message || t('Cancel failed'))
    console.error('Cancel failed:', error)
  } finally {
    loading.value = false
  }
}

// Ctrl/Cmd + S 快捷保存
function handleKeydownSave(e: KeyboardEvent) {
  // 仅在按下 Ctrl/Cmd + S 时触发
  if ((e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'S')) {
    e.preventDefault()
    if (canEdit.value && !loading.value) {
      // 不等待，保持与按钮点击一致的交互
      handleSave()
    }
  }
}

// 返回列表页（从 history.state 恢复页码）
function goBack() {
  // 从 history.state 获取列表页的页码
  const listPage = history.state?._listPage || 1
  
  router.push({ 
    name: 'PageTypeList', 
    params: { entity: pagetypeSlug.value },
    query: listPage > 1 ? { page: listPage } : {}
  })
}

// 刷新详情数据
async function handleRefresh() {
  if (loading.value || isNew.value) return
  
  try {
    await loadDetail()
  } catch (error) {
    message.error(t('Failed to refresh'))
    console.error('Refresh error:', error)
  }
}

// 删除记录
async function handleDelete() {
  if (loading.value || isNew.value) return
  
  const recordName = record.name || id.value
  if (!recordName) {
    message.error(t('Cannot delete record without name'))
    return
  }
  
  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 result = await deleteRecords(entity.value, [recordName])
        if (result.success) {
          message.success(result.message || t('Deleted successfully'))
          // 删除成功后跳转到列表页
          router.push({ name: 'PageTypeList', params: { entity: pagetypeSlug.value } })
        } else {
          message.error(result.message || t('Failed to delete'))
        }
      } catch (error) {
        message.error(t('Failed to delete'))
        console.error('Delete error:', error)
      } finally {
        loading.value = false
      }
    }
  })
}

// 重命名记录后跳转到新名称
// With enqueue=false, rename is synchronous. API returns when rename is complete,
// so we can navigate to the new name immediately.
function handleRename(newName: string) {
  if (!newName) return

  const oldName = id.value

  if (newName !== oldName) {
    message.success(t('Page renamed from {0} to {1}', [oldName, newName]))
    router.push({
      name: 'PageTypeDetail',
      params: { entity: pagetypeSlug.value, id: newName }
    })
  } else {
    loadDetail()
  }
}

// 重复记录：与旧版对齐，导航到新建页面并预填副本数据，用户手动保存
function handleDuplicate(_newName: string) {
  // 生成与新建一致的临时ID格式：new-{pagetypeSlug}-{randomStr}
  const randomStr = Math.random().toString(36).substring(2, 12)
  const tempName = `new-${pagetypeSlug.value}-${randomStr}`
  router.push({
    name: 'PageTypeDetail',
    params: { entity: pagetypeSlug.value, id: tempName }
  })
}

const isSaving = ref(false) // 标记当前用户是否正在保存，防止自触发的 pg_update 导致重复刷新

// Realtime: 监听文档更新事件
const realtime = useRealtime()

function handlePgUpdate(data: PgUpdateData) {
  // 忽略自己保存触发的更新
  if (isSaving.value) return
  // 检查是否是当前查看的文档
  if (data.pagetype !== entity.value || data.name !== id.value) return
  // 检查是否真的有变化（modified 不同才刷新）
  if (data.modified && data.modified === record.modified) return
  // 脏检查：用户有未保存的修改时，仅提示不自动刷新
  try {
    if (JSON.stringify(record) !== JSON.stringify(originalRecord.value)) {
      message.info(t('This document has been updated by another user. Please refresh to see the latest changes.'))
      return
    }
  } catch { /* ignore */ }
  // 无本地修改，自动静默刷新
  loadDetail()
}

onMounted(async () => {
  // Load plugins
  await loadAllPlugins()

  // 注册快捷键监听
  window.addEventListener('keydown', handleKeydownSave, { capture: true })

  // 加载侧边栏用户偏好设置
  loadSidebarPreferences()

  // 解析工具栏覆盖组件
  const tb = await resolvePagetypeToolbarOverride(pagetypeSlug.value)
  toolbarComponent.value = tb ? markRaw(tb) : null

  await loadMeta()
  await loadDetail()

  // 初次加载完成
  initialLoading.value = false

  // 订阅文档实时更新
  if (!isNew.value && id.value) {
    realtime.watchDocument(entity.value, id.value, {
      onUpdate: handlePgUpdate
    })
  }
})

onUnmounted(() => {
  // 必须与注册时的 capture 选项一致，否则无法移除监听
  window.removeEventListener('keydown', handleKeydownSave, { capture: true } as any)
})

// 监听路由参数变化
// 使用单一 watcher 同时监听 entity 和 id，避免跨实体导航时双重 loadDetail() 调用
watch(
  () => ({ entity: route.params.entity, id: route.params.id }),
  async (newVal, oldVal) => {
    const entityChanged = newVal.entity !== oldVal.entity
    const idChanged = newVal.id !== oldVal.id

    if (!entityChanged && !idChanged) return

    if (entityChanged) {
      // Entity changed: reload toolbar, meta and detail
      const tb = await resolvePagetypeToolbarOverride(String(newVal.entity))
      toolbarComponent.value = tb ? markRaw(tb) : null
      await loadMeta()
      await loadDetail()
      // Re-subscribe realtime for the new document
      if (!isNew.value && String(newVal.id)) {
        realtime.watchDocument(entity.value, String(newVal.id), {
          onUpdate: handlePgUpdate
        })
      }
    } else if (idChanged) {
      // Only id changed: reload detail + re-subscribe realtime
      await loadDetail()
      if (!isNew.value && String(newVal.id)) {
        realtime.watchDocument(entity.value, String(newVal.id), {
          onUpdate: handlePgUpdate
        })
      }
    }
  }
)
</script>

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

.page-header {
  margin-bottom: 24px;
}

.page-title {
  font-size: 28px;
  font-weight: 600;
  color: #1f2937;
  margin: 0 0 8px 0;
}

.page-description {
  font-size: 16px;
  color: #6b7280;
  margin: 0;
}

/* Jingrow 风格的 Form Layout */
.form-layout {
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
}

.form-page {
  padding: 32px;
}

/* Tabs */
.form-tabs-list {
  border-bottom: 1px solid #e5e7eb;
  margin-bottom: 24px;
}

.nav.form-tabs {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-item {
  margin-right: 8px;
}

.nav-link {
  display: block;
  padding: 12px 16px;
  color: #6b7280;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  transition: all 0.2s;
}

.nav.li.nav-item a:hover {
  color: #2563eb;
}

.nav-link.active {
  color: #2563eb;
  border-bottom-color: #2563eb;
}

/* Tab Content */
.form-tab-content {
  min-height: 400px;
}

.tab-pane {
  display: none;
}

.tab-pane.active {
  display: block;
}

/* Sections */
.form-sections {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.form-section {
  border-radius: 8px;
}

.section-header h4 {
  font-size: 18px;
  font-weight: 600;
  color: #1f2937;
  margin: 0 0 20px 0;
  border-bottom: 1px solid #e5e7eb;
  padding-bottom: 8px;
}

.section-body {
  display: grid;
  gap: 24px;
}

/* Columns */
.form-column {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Two column layout */
.section-body:has(.form-column:nth-child(2)) {
  grid-template-columns: 1fr 1fr;
}

/* Three column layout */
.section-body:has(.form-column:nth-child(3)) {
  grid-template-columns: 1fr 1fr 1fr;
}

/* Four column layout */
.section-body:has(.form-column:nth-child(4)) {
  grid-template-columns: 1fr 1fr 1fr 1fr;
}

/* Five column layout */
.section-body:has(.form-column:nth-child(5)) {
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
}

/* Six column layout */
.section-body:has(.form-column:nth-child(6)) {
  grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
}

/* Fields */
.form-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.field-label {
  display: flex;
  align-items: center;
  gap: 4px;
}

/* 通用字段样式 */
.field-wrapper {
  display: flex;
  width: 100%;
}

.field-wrapper.layout-vertical {
  flex-direction: column;
  gap: 6px;
}

.field-wrapper.layout-horizontal {
  flex-direction: row;
  align-items: center;
  gap: 12px;
}

.field-wrapper.layout-horizontal .field-label {
  min-width: 100px;
  flex-shrink: 0;
}

.field-label {
  font-weight: 500;
  color: #374151;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.required {
  color: #ef4444;
  font-weight: bold;
}

.field-content {
  min-height: 32px;
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  width: 100%;
}

/* 确保所有输入组件都是全宽的 */
.field-content :deep(.n-input),
.field-content :deep(.n-select),
.field-content :deep(.n-input-number),
.field-content :deep(.n-date-picker),
.field-content :deep(.n-time-picker),
.field-content :deep(.n-rate),
.field-content :deep(.n-color-picker),
.field-content :deep(.n-auto-complete) {
  width: 100%;
}

.field-value {
  color: #111827;
  font-size: 14px;
  word-break: break-word;
}

.json-content {
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  padding: 12px;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 200px;
  overflow-y: auto;
}

/* JSON 字段容器样式 */
.json-field-container {
  position: relative;
  width: 100%;
}

/* JSON 输入框样式 */
.json-textarea {
  width: 100%;
}

.json-textarea :deep(.n-input__input-el) {
  font-family: 'Courier New', monospace !important;
  font-size: 12px !important;
  line-height: 1.4 !important;
  white-space: pre !important;
  overflow-wrap: normal !important;
  width: 100% !important;
}

/* 特殊字段类型样式 */
.multicheck-container {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.signature-container,
.image-container,
.attach-container,
.attach-image-container,
.table-multiselect-container {
  padding: 12px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  min-height: 40px;
  display: flex;
  align-items: center;
}

.table-container {
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 0;
  min-height: auto;
  display: block;
  align-items: stretch;
}

.field-heading {
  font-size: 18px;
  font-weight: 600;
  color: #1f2937;
  margin: 0;
  padding: 8px 0;
  border-bottom: 1px solid #e5e7eb;
}

.html-content {
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  padding: 12px;
  min-height: 40px;
}

/* Seen By 折叠与徽章样式 */
.seen-by-block {
  width: 100%;
}
.seen-by-header {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  color: #374151;
  user-select: none;
}
.seen-by-title {
  font-weight: 500;
}
.seen-by-count {
  margin: 0 6px;
  color: #9ca3af;
  font-size: 12px;
}
.seen-by-chips {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.seen-by-chip {
  background: #f3f4f6;
}
.chip-text {
  padding: 0 2px;
}
.fade-enter-active, .fade-leave-active { transition: opacity .15s ease; }
.fade-enter-from, .fade-leave-to { opacity: 0; }

/* 收起态去除多余高度与间距 */
.field-content.seen-by-collapsed {
  min-height: 0;
  padding: 0;
}

/* 统一的系统信息页脚 */
.meta-footer {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 24px 20px 24px;
  color: #6b7280;
  font-size: 13px;
}
.meta-item {
  display: flex;
  align-items: center;
  gap: 6px;
}
.meta-label {
  color: #9ca3af;
}
.meta-value {
  color: #374151;
}
.meta-sep {
  width: 1px;
  height: 16px;
  background: #e5e7eb;
}

/* 主布局容器 - 使用 Naive UI Layout */
.detail-page-layout {
  min-height: calc(100vh - 120px);
}

/* 初次加载容器 */
.loading-container {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 400px;
}

.loading-spinner {
  width: 40px;
  height: 40px;
  border: 3px solid #f3f4f6;
  border-top-color: #3b82f6;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* 平滑过渡，减少布局闪烁 */
.detail-page-layout :deep(.n-layout-sider) {
  transition: width 0.3s ease, transform 0.3s ease;
}

.detail-page-layout :deep(.n-layout-content) {
  transition: margin-left 0.3s ease, margin-right 0.3s ease;
}

/* 主内容区域 */
.main-content {
  min-width: 0; 
  position: relative; 
  overflow: visible !important; 
}

/* 强制覆盖 Naive UI Layout Content 的样式 */
.detail-page-layout :deep(.n-layout-content) {
  overflow: visible !important;
}

.detail-page-layout :deep(.n-layout) {
  overflow: visible !important;
}

/* 确保所有父级容器都允许溢出 */
.generic-detail-page {
  overflow: visible !important;
}

/* 只对特定的布局容器设置 overflow: visible，避免影响 SchemaBuilder */
.generic-detail-page .detail-page-layout,
.generic-detail-page .detail-page-layout * {
  overflow: visible;
}

/* 侧边栏控制按钮 */
.sidebar-toggle-btn {
  position: absolute;
  top: -10px;
  z-index: 1000;
}

/* 左侧边栏控制按钮 */
.sidebar-toggle-btn.toggle-left {
  left: -10px;
}

/* 右侧边栏控制按钮 */
.sidebar-toggle-btn.toggle-right {
  right: -10px;
}

.toggle-button {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #ffffff !important;
  border: 1px solid var(--n-border-color);
  color: var(--n-text-color);
  box-shadow: none;
  transition: all 0.2s ease;
}

.toggle-button:hover {
  background: #f5f5f5 !important;
  color: var(--n-text-color-hover);
  transform: none;
  box-shadow: none;
}

.toggle-button:active {
  transform: none;
  background: #d1d5db !important;
}


/* 响应式设计 - Naive UI Layout 自动处理 */
@media (max-width: 768px) {
  .generic-detail-page {
    padding: 8px;
  }
  
  .page-header {
    margin-bottom: 16px;
  }
  
  .page-title {
    font-size: 24px;
  }
  
  .form-page {
    padding: 16px;
  }
  
  /* 移动端侧边栏控制按钮调整 */
  .sidebar-toggle-btn.toggle-left {
    left: -8px;
  }
  
  .sidebar-toggle-btn.toggle-right {
    right: -8px;
  }
  
  .toggle-button {
    width: 20px;
    height: 20px;
  }
}

@media (min-width: 768px) and (max-width: 1024px) {
  .generic-detail-page {
    padding: 12px;
  }
  
  .form-page {
    padding: 24px;
  }
}

@media (min-width: 1024px) {
  .generic-detail-page {
    padding: 16px;
  }
  
  .form-page {
    padding: 32px;
  }
}
</style>