<script setup lang="ts">
// Keyword Research 专用的 Table 控件覆盖
// 在 keywords 字段添加批量添加功能
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { NModal, NButton, NSpace, NConfigProvider } from 'naive-ui'
import FieldRenderer from '@/core/pagetype/form/FieldRenderer.vue'
import Link from '@/core/pagetype/form/controls/Link.vue'
import Date from '@/core/pagetype/form/controls/Date.vue'
import Float from '@/core/pagetype/form/controls/Float.vue'
import Currency from '@/core/pagetype/form/controls/Currency.vue'
import { getPageTypeMeta } from '@/shared/api/common'

const props = defineProps<{ 
  df: any; 
  record: Record<string, any>; 
  canEdit: boolean; 
  ctx: any;
  modelValue?: any;
  disabled?: boolean;
}>()

// 是否启用批量添加功能（仅针对 keywords 字段）
const enableBatchAdd = computed(() => props.df.fieldname === 'keywords')

const labelLayout = computed(() => props.df.label_layout || 'vertical')

const buttonThemeOverrides = {
  Button: {
    colorDefault: '#f3f4f6',
    colorHoverDefault: '#e5e7eb',
    colorPressedDefault: '#d1d5db',
    textColorDefault: '#374151',
    textColorHoverDefault: '#374151',
    textColorPressedDefault: '#374151',
    borderDefault: '1px solid #d1d5db',
    borderHoverDefault: '1px solid #9ca3af',
    borderPressedDefault: '1px solid #9ca3af',
  }
}

const seenByExpanded = ref(false)
const seenByUsers = computed(() => {
  const list = Array.isArray(props.record?.seen_by) ? props.record.seen_by : []
  return list.map((item: any, idx: number) => ({
    key: item.name || item.user || String(idx),
    label: item.user || item.owner || '—'
  }))
})

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

type Field = { label: string; fieldname: string; fieldtype: string; in_list_view?: boolean; columns?: number; options?: string }

const loading = ref(false)
const childFields = ref<Field[]>([])

const rows = computed<any[]>(() => {
  const value = (props.record as any)?.[props.df.fieldname]
  return Array.isArray(value) ? value : []
})

// 排序后的行
const sortedRows = computed(() => {
  if (!sortField.value) return rows.value
  const field = sortField.value
  const order = sortOrder.value
  return [...rows.value].sort((a, b) => {
    let va = a[field]
    let vb = b[field]
    // 数字排序
    if (typeof va === 'number' && typeof vb === 'number') {
      return order === 'asc' ? va - vb : vb - va
    }
    // 字符串排序
    va = String(va ?? '')
    vb = String(vb ?? '')
    return order === 'asc' ? va.localeCompare(vb) : vb.localeCompare(va)
  })
})

// 渐进式行渲染：避免一次性挂载大量DOM节点阻塞主线程
const BATCH_SIZE = 50
const displayLimit = ref(BATCH_SIZE)
let rafId: number | null = null

const visibleRows = computed(() => sortedRows.value.slice(0, displayLimit.value))
const hasMoreRows = computed(() => displayLimit.value < sortedRows.value.length)

function progressiveRender() {
  if (displayLimit.value >= sortedRows.value.length) return
  displayLimit.value = Math.min(displayLimit.value + BATCH_SIZE, sortedRows.value.length)
  rafId = requestAnimationFrame(progressiveRender)
}

function startProgressiveRender() {
  if (rafId !== null) cancelAnimationFrame(rafId)
  displayLimit.value = Math.min(BATCH_SIZE, sortedRows.value.length)
  if (sortedRows.value.length > BATCH_SIZE) {
    rafId = requestAnimationFrame(progressiveRender)
  }
}

const selectedRows = ref<Set<number>>(new Set())
const selectAll = ref(false)

const showEditModal = ref(false)
const editIndex = ref<number | null>(null)
const editForm = ref<Record<string, any>>({})

// 批量添加关键词状态
const showBatchAddModal = ref(false)
const batchKeywordsText = ref('')

// 文件导入
const fileInput = ref<HTMLInputElement | null>(null)

// 排序状态
const sortField = ref<string>('')
const sortOrder = ref<'asc' | 'desc'>('asc')

const editingCell = ref<{ rowIndex: number; fieldName: string } | null>(null)

const childTabs = computed(() => {
  const fields = childFields.value
  const result: any[] = []
  let currentTab: any = null
  let currentSection: any = null
  let currentColumn: any = null
  
  const hasTabBreak = fields.some(field => field.fieldtype === 'Tab Break')
  if (!hasTabBreak) {
    currentTab = { key: 'default', label: t('Detail'), sections: [] }
  }
  
  for (const field of fields) {
    switch (field.fieldtype) {
      case 'Tab Break':
        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 })
          }
        }
        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':
        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 })
          }
        }
        currentSection = { key: field.fieldname || field.label || `section_${currentTab ? currentTab.sections.length + 1 : 1}`, label: field.label || '', columns: [] }
        currentColumn = null
        break
        
      case 'Column Break':
        if (!currentTab) currentTab = { key: 'default', label: t('Detail'), sections: [] }
        if (!currentSection) currentSection = { key: 'default', label: '', columns: [] }
        if (currentColumn && currentColumn.fields.length > 0) {
          if (!currentSection.columns) currentSection.columns = []
          currentSection.columns.push({ ...currentColumn })
        }
        currentColumn = { key: `column_${currentSection.columns ? currentSection.columns.length : 0}`, fields: [] }
        break
        
      default:
        if (['Tab Break', 'Section Break', 'Column Break'].includes(field.fieldtype)) break
        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
    }
  }
  
  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 t = (key: string) => (props.ctx?.t ? props.ctx.t(key) : key)

// 格式化搜索量为范围显示
function formatSearchVolume(value: any): string {
  if (value === '' || value === null || value === undefined) return ''
  const num = Number(value)
  if (isNaN(num) || num === 0) return ''
  
  if (num <= 10) return t('< 10')
  if (num <= 100) return t('10 - 100')
  if (num <= 1000) return t('100 - 1K')
  if (num <= 10000) return t('1K - 10K')
  if (num <= 100000) return t('10K - 100K')
  if (num <= 1000000) return t('100K - 1M')
  if (num <= 10000000) return t('1M - 10M')
  return t('> 10M')
}

// 格式化竞争程度显示
function formatCompetition(value: any): string {
  if (!value) return ''
  const v = String(value).trim()
  if (v === 'Low') return t('Low')
  if (v === 'Medium') return t('Medium')
  if (v === 'High') return t('High')
  return value
}

// 格式化Int类型字段，0或空显示为空
function formatIntValue(value: any): string {
  if (value === '' || value === null || value === undefined) return ''
  const num = Number(value)
  if (isNaN(num) || num === 0) return ''
  return String(value)
}

// 根据字段名获取格式化后的显示值
function getDisplayValue(meta: any, value: any): string {
  const fn = meta.fieldname
  if (fn === 'monthly_search_volume') return formatSearchVolume(value)
  if (fn === 'competition_level') return formatCompetition(value)
  if (meta.fieldtype === 'Int') return formatIntValue(value)
  return value ?? ''
}

async function loadChildMeta() {
  const pagetype = props.df?.options
  if (!pagetype) return
  loading.value = true
  try {
    const result = await getPageTypeMeta(pagetype)
    if (result.success && result.data) {
      childFields.value = result.data.fields || []
    }
  } catch (error) {
    console.error('Failed to load child meta for', pagetype, ':', error)
  } finally {
    loading.value = false
  }
}

function getTableColumns() {
  const table_fields = childFields.value
  const columns: Array<[Partial<Field>, number]> = []
  let total = 1
  columns.push([{ label: t('No.') }, 0.5])

  for (const tf of table_fields) {
    if (['Section Break', 'Column Break', 'Tab Break'].includes(tf.fieldtype)) continue
    if (!tf.in_list_view || !tf.label) continue
    let colsize = ['Date', 'Datetime'].includes(tf.fieldtype) 
      ? Math.max(tf.columns ? Number(tf.columns) : 0, 3)
      : (tf.columns ? Number(tf.columns) : defaultCol(tf))
    if (total > 11 + colsize) continue
    total += colsize
    columns.push([{ label: tf.label, fieldname: tf.fieldname, fieldtype: tf.fieldtype, options: tf.options }, colsize])
  }

  function defaultCol(f: Field) {
    if (['Int', 'Check', 'Percent'].includes(f.fieldtype)) return 1
    if (['Float', 'Currency'].includes(f.fieldtype)) return 2
    if (['Link', 'Text', 'Long Text', 'Date', 'Datetime'].includes(f.fieldtype)) return 3
    return 2
  }

  columns.forEach(col => { if (col[1] > 1 && col[1] < 11 && total < 11) { col[1]++; total++ } })
  return columns
}

const columns = computed(() => getTableColumns())

function addRow() {
  if (!props.canEdit) return
  const arr = Array.isArray((props.record as any)[props.df.fieldname]) 
    ? (props.record as any)[props.df.fieldname] 
    : (((props.record as any)[props.df.fieldname] = []), (props.record as any)[props.df.fieldname])
  const idx = (arr?.length || 0) + 1
  const row: any = { idx }
  for (const [meta] of columns.value.slice(1)) {
    const fn = (meta as any).fieldname
    if (fn && !(fn in row)) row[fn] = ''
  }
  arr.push(row)
}

// 批量添加关键词
function batchAddKeywords() {
  if (!props.canEdit) return
  const text = batchKeywordsText.value.trim()
  if (!text) { showBatchAddModal.value = false; return }
  
  const keywords = text.split('\n').map(k => k.trim()).filter(k => k.length > 0).slice(0, 10000)
  if (keywords.length === 0) { showBatchAddModal.value = false; return }
  
  const arr = Array.isArray((props.record as any)[props.df.fieldname]) 
    ? (props.record as any)[props.df.fieldname] 
    : (((props.record as any)[props.df.fieldname] = []), (props.record as any)[props.df.fieldname])
  
  const startIdx = (arr?.length || 0) + 1
  keywords.forEach((keyword, i) => {
    const row: any = { idx: startIdx + i, keyword }
    for (const [meta] of columns.value.slice(1)) {
      const fn = (meta as any).fieldname
      if (fn && fn !== 'keyword' && !(fn in row)) row[fn] = ''
    }
    arr.push(row)
  })
  
  batchKeywordsText.value = ''
  showBatchAddModal.value = false
}

// 触发文件选择
function triggerImport() {
  if (!props.canEdit) return
  fileInput.value?.click()
}

// 解析 Google Keyword Planner CSV
function parseGKPcsv(content: string) {
  const lines = content.split('\n')
  if (lines.length < 2) return []
  
  // 自动检测CSV格式：检查第一行是否包含 Keyword 字段
  const firstLineHeaders = parseCSVLine(lines[0])
  const hasKeywordInFirstLine = firstLineHeaders.includes('Keyword')
  
  let headerLineIndex: number
  let dataStartIndex: number
  
  if (hasKeywordInFirstLine) {
    // 简化格式：第一行是表头，第二行开始是数据
    headerLineIndex = 0
    dataStartIndex = 1
  } else {
    // 完整GKP格式：跳过前两行（标题和日期范围），第三行是表头
    if (lines.length < 4) return []
    headerLineIndex = 2
    dataStartIndex = 3
  }
  
  const headers = parseCSVLine(lines[headerLineIndex])
  
  // 找到需要的列索引
  const keywordIdx = headers.indexOf('Keyword')
  const avgSearchIdx = headers.indexOf('Avg. monthly searches')
  const competitionIdx = headers.indexOf('Competition')
  const competitionIndexedIdx = headers.indexOf('Competition (indexed value)')
  const bidLowIdx = headers.indexOf('Top of page bid (low range)')
  const bidHighIdx = headers.indexOf('Top of page bid (high range)')
  
  if (keywordIdx === -1) return []
  
  const results: any[] = []
  
  // 从数据起始行开始解析
  for (let i = dataStartIndex; i < lines.length && results.length < 10000; i++) {
    const line = lines[i]
    if (!line.trim()) continue
    
    const values = parseCSVLine(line)
    const keyword = values[keywordIdx]?.trim()
    
    // 跳过没有关键词的行（分组行）
    if (!keyword) continue
    
    // 解析月均搜索量
    let monthlySearchVolume = ''
    const avgSearch = values[avgSearchIdx]?.trim()
    if (avgSearch) {
      // 处理数字格式，移除逗号
      monthlySearchVolume = avgSearch.replace(/,/g, '')
    }
    
    // 解析竞争程度（低/中/高 -> Low/Medium/High）
    let competitionLevel = ''
    const competition = values[competitionIdx]?.trim()
    if (competition === '低') competitionLevel = 'Low'
    else if (competition === '中') competitionLevel = 'Medium'
    else if (competition === '高') competitionLevel = 'High'
    
    // 解析竞争指数值
    let competitionIndexedValue = ''
    const compIndexed = values[competitionIndexedIdx]?.trim()
    if (compIndexed) {
      competitionIndexedValue = compIndexed.replace(/,/g, '')
    }
    
    results.push({
      keyword,
      monthly_search_volume: monthlySearchVolume ? parseInt(monthlySearchVolume, 10) || '' : '',
      competition_level: competitionLevel,
      competition_indexed_value: competitionIndexedValue ? parseInt(competitionIndexedValue, 10) || '' : '',
      top_of_page_bid_low_range: values[bidLowIdx]?.trim() || '',
      top_of_page_bid_high_range: values[bidHighIdx]?.trim() || ''
    })
  }
  
  return results
}

// 解析CSV行（处理制表符分隔）
function parseCSVLine(line: string): string[] {
  return line.split('\t').map(cell => cell.trim())
}

// 处理文件导入
function handleFileImport(event: Event) {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  if (!file) return
  
  const reader = new FileReader()
  reader.onload = (e) => {
    const content = e.target?.result as string
    const keywords = parseGKPcsv(content)
    
    if (keywords.length === 0) return
    
    const arr = Array.isArray((props.record as any)[props.df.fieldname]) 
      ? (props.record as any)[props.df.fieldname] 
      : (((props.record as any)[props.df.fieldname] = []), (props.record as any)[props.df.fieldname])
    
    const startIdx = (arr?.length || 0) + 1
    keywords.forEach((kw, i) => {
      const row: any = { 
        idx: startIdx + i,
        keyword: kw.keyword,
        monthly_search_volume: kw.monthly_search_volume,
        competition_level: kw.competition_level,
        competition_indexed_value: kw.competition_indexed_value,
        top_of_page_bid_low_range: kw.top_of_page_bid_low_range,
        top_of_page_bid_high_range: kw.top_of_page_bid_high_range
      }
      // 预置其他字段为空值
      for (const [meta] of columns.value.slice(1)) {
        const fn = (meta as any).fieldname
        if (fn && !(fn in row)) row[fn] = ''
      }
      arr.push(row)
    })
  }
  reader.readAsText(file, 'UTF-8')
  
  // 清空input以便重复选择同一文件
  input.value = ''
}

function removeRow(i: number) {
  if (!props.canEdit) return
  const arr = rows.value
  if (!arr?.length) return
  // 通过对象引用找到原始索引
  const rowToDelete = sortedRows.value[i]
  const originalIndex = arr.indexOf(rowToDelete)
  if (originalIndex > -1) {
    arr.splice(originalIndex, 1)
    arr.forEach((r: any, j: number) => (r.idx = j + 1))
  }
  selectedRows.value.clear()
  selectAll.value = false
}

function toggleSelectAll() {
  if (selectAll.value) {
    selectedRows.value.clear()
  } else {
    selectedRows.value = new Set(Array.from({ length: rows.value.length }, (_, i) => i))
  }
  selectAll.value = !selectAll.value
}

function toggleRowSelect(index: number) {
  if (selectedRows.value.has(index)) {
    selectedRows.value.delete(index)
  } else {
    selectedRows.value.add(index)
  }
  selectAll.value = selectedRows.value.size === rows.value.length
}

// 切换排序
function toggleSort(fieldname: string) {
  if (sortField.value === fieldname) {
    sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
  } else {
    sortField.value = fieldname
    sortOrder.value = 'asc'
  }
  // 排序变更后重置渐进渲染
  startProgressiveRender()
}

function editRow(index: number) {
  if (!props.canEdit) return
  const row = sortedRows.value[index]
  if (!row) return
  editIndex.value = index
  const data: Record<string, any> = {}
  childFields.value.forEach((f) => {
    if (f.fieldname && f.fieldname !== 'idx') {
      data[f.fieldname] = row[f.fieldname] ?? ''
    }
  })
  editForm.value = data
  showEditModal.value = true
}

function saveEdit() {
  if (editIndex.value == null) return
  const row = sortedRows.value[editIndex.value]
  Object.keys(editForm.value).forEach((k) => { row[k] = editForm.value[k] })
  showEditModal.value = false
}

function batchDelete() {
  if (!props.canEdit || selectedRows.value.size === 0) return
  const arr = rows.value
  const indicesToDelete = Array.from(selectedRows.value).sort((a, b) => b - a)
  indicesToDelete.forEach(i => arr.splice(i, 1))
  arr.forEach((r: any, j: number) => (r.idx = j + 1))
  selectedRows.value.clear()
  selectAll.value = false
}

function startInlineEdit(rowIndex: number, fieldName: string) {
  if (!props.canEdit) return
  editingCell.value = { rowIndex, fieldName }
}

function isFieldEditable(field: any) {
  if (['Tab Break', 'Section Break', 'Column Break'].includes(field.fieldtype)) return false
  if (field.hidden === 1 || field.hidden === true || field.hidden === '1') return false
  if (field.depends_on) {
    try {
      if (field.depends_on.startsWith('eval:')) {
        const code = field.depends_on.substring(5)
        return !!(new Function('pg', `return !!(${code})`)(props.record))
      }
      return !!props.record[field.depends_on]
    } catch { return false }
  }
  return true
}

function handleClickOutside(event: Event) {
  if (!editingCell.value) return
  const target = event.target as HTMLElement
  if (!target.closest('.inline-edit-input') && !target.closest('.link-field-container') && 
      !target.closest('.n-date-picker') && !target.closest('.n-date-panel') && 
      !target.closest('.n-input-number') && !target.closest('.n-base-select-menu')) {
    editingCell.value = null
  }
}

onMounted(() => {
  loadChildMeta()
  document.addEventListener('click', handleClickOutside)
  // 启动渐进式行渲染
  startProgressiveRender()
})

onUnmounted(() => {
  document.removeEventListener('click', handleClickOutside)
  if (rafId !== null) cancelAnimationFrame(rafId)
})
</script>

<template>
  <!-- Seen By 特殊布局 -->
  <template v-if="df.fieldname === 'seen_by'">
    <div class="seen-by-block">
      <div class="field-label">
        <div class="seen-by-header" @click="toggleSeenBy()">
          <label>{{ ctx?.t ? ctx.t(df.label || df.fieldname) : (df.label || df.fieldname) }}</label>
          <span class="seen-by-count">{{ seenByUsers.length }}</span>
        </div>
      </div>
    </div>
  </template>
  
  <!-- 标准Table布局 -->
  <div v-else :class="['field-wrapper', `layout-${labelLayout}`]">
    <label class="field-label">
      {{ ctx?.t ? ctx.t(df.label || df.fieldname) : (df.label || df.fieldname) }}
      <span v-if="df.reqd" class="required">*</span>
    </label>
    <div class="table-container">
      <template v-if="columns.length > 0">
        <div class="table-grid">
          <div class="table-head">
            <div class="table-cell head checkbox" v-if="canEdit" style="width: 4%">
              <input type="checkbox" :checked="selectAll" @change="toggleSelectAll" />
            </div>
            <div v-for="([meta, size], i) in columns" :key="i" 
              :class="['table-cell', 'head', { 'sortable': i > 0 }]"
              :style="i === 0 ? { width: '5%', minWidth: '40px' } : { width: (size * 8) + '%' }"
              @click="i > 0 && toggleSort((meta as any).fieldname)">
              <span class="sort-label">{{ t((meta as any).label) }}</span>
              <span v-if="i > 0 && sortField === (meta as any).fieldname" class="sort-icon">
                {{ sortOrder === 'asc' ? '↑' : '↓' }}
              </span>
            </div>
            <div class="table-cell head actions" v-if="canEdit" style="width: 8%">{{ t('Actions') }}</div>
          </div>

          <div class="table-body" v-if="visibleRows.length">
            <div class="table-row" v-for="(r, i) in visibleRows" :key="i">
              <div class="table-cell checkbox" v-if="canEdit" style="width: 4%">
                <input type="checkbox" :checked="selectedRows.has(i)" @change="toggleRowSelect(i)" />
              </div>
              <div v-for="([meta, size], k) in columns" :key="k" class="table-cell"
                :style="k === 0 ? { width: '5%', minWidth: '40px' } : { width: (size * 8) + '%' }">
                <template v-if="k === 0">{{ i + 1 }}</template>
                <template v-else>
                  <template v-if="editingCell?.rowIndex === i && editingCell?.fieldName === (meta as any).fieldname">
                    <template v-if="(meta as any).fieldtype === 'Link'">
                      <Link :df="meta" :record="visibleRows[i]" :canEdit="canEdit" :ctx="ctx" :onlyInput="true" />
                    </template>
                    <template v-else-if="(meta as any).fieldtype === 'Date' || (meta as any).fieldtype === 'Datetime'">
                      <Date :df="meta" :record="visibleRows[i]" :canEdit="canEdit" :ctx="ctx" :onlyInput="true" />
                    </template>
                    <template v-else-if="(meta as any).fieldtype === 'Float' || (meta as any).fieldtype === 'Int'">
                      <Float :df="meta" :record="visibleRows[i]" :canEdit="canEdit" :ctx="ctx" :onlyInput="true" />
                    </template>
                    <template v-else-if="(meta as any).fieldtype === 'Currency'">
                      <Currency :df="meta" :record="visibleRows[i]" :canEdit="canEdit" :ctx="ctx" :onlyInput="true" />
                    </template>
                    <template v-else>
                      <input v-model="visibleRows[i][(meta as any).fieldname]" class="inline-edit-input" autofocus />
                    </template>
                  </template>
                  <template v-else>
                    <span v-if="!canEdit || !isFieldEditable(meta)" class="cell-display">
                      {{ getDisplayValue(meta, r[(meta as any).fieldname]) }}
                    </span>
                    <span v-else class="cell-display editable-cell" @click.stop="startInlineEdit(i, (meta as any).fieldname)"
                      :title="t('Click to edit') + ' ' + t((meta as any).label)">
                      {{ getDisplayValue(meta, r[(meta as any).fieldname]) }}
                    </span>
                  </template>
                </template>
              </div>
              <div class="table-cell actions" v-if="canEdit" style="width: 8%">
                <button class="link-btn edit-btn" type="button" @click="editRow(i)" title="编辑"><i class="fa-regular fa-edit"></i></button>
                <button class="link-btn delete-btn" type="button" @click="removeRow(i)" title="删除"><i class="fa-regular fa-trash-can"></i></button>
              </div>
            </div>
          </div>

          <div class="grid-empty" v-else><span>{{ t('No Data') }}</span></div>
        </div>

        <div class="grid-footer" v-if="canEdit">
          <div class="footer-actions">
            <button v-if="selectedRows.size > 0" class="btn btn-danger" type="button" @click="batchDelete">
              {{ t('Delete') }} ({{ selectedRows.size }})
            </button>
            <n-config-provider :theme-overrides="buttonThemeOverrides">
              <n-button type="default" @click="addRow">{{ t('Add Row') }}</n-button>
              <n-button v-if="enableBatchAdd" type="default" class="batch-add-btn" @click="showBatchAddModal = true">{{ t('Batch Add') }}</n-button>
              <n-button v-if="enableBatchAdd" type="default" class="import-btn" @click="triggerImport" :title="t('Support Google Keyword Planner CSV format')">{{ t('Import') }}</n-button>
              <input v-if="enableBatchAdd" ref="fileInput" type="file" accept=".csv,.tsv" class="hidden-input" @change="handleFileImport" />
            </n-config-provider>
            <span v-if="hasMoreRows" class="row-count-hint">{{ t('Showing') }} {{ visibleRows.length }} / {{ sortedRows.length }}</span>
          </div>
        </div>
      </template>
      <template v-else>
        <span class="field-value">{{ loading ? t('Loading') + '…' : '—' }}</span>
      </template>
      
      <!-- 编辑弹窗 -->
      <n-modal v-model:show="showEditModal" :show-icon="false" :mask-closable="true"
        :style="{ width: '90%', maxWidth: '1200px' }" :auto-focus="false" preset="card" :title="t('Edit Child Row')">
        <div class="child-form-layout">
          <div v-for="tab in childTabs" :key="tab.key" class="form-tab">
            <div v-for="section in tab.sections" :key="section.key" class="form-section">
              <div v-if="section.label" class="section-header"><h4 class="section-title">{{ section.label }}</h4></div>
              <div class="section-body">
                <div v-for="column in section.columns" :key="column.key" class="form-column">
                  <div v-for="field in column.fields" :key="field.fieldname" class="form-field">
                    <FieldRenderer :df="{ ...field, fieldname: field.fieldname }" :record="editForm" :canEdit="canEdit" :ctx="ctx" />
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <template #footer>
          <div class="modal-footer">
            <n-space>
              <n-button @click="showEditModal = false">{{ t('Cancel') }}</n-button>
              <n-button type="primary" @click="saveEdit">{{ t('Save') }}</n-button>
            </n-space>
          </div>
        </template>
      </n-modal>
      
      <!-- 批量添加关键词弹窗 -->
      <n-modal v-model:show="showBatchAddModal" :show-icon="false" :mask-closable="true"
        :style="{ width: '90%', maxWidth: '600px' }" :auto-focus="false" preset="card" :title="t('Batch Add Keywords')">
        <div class="batch-add-content">
          <p class="batch-hint">{{ t('Enter keywords, one per line. Max 10,000 keywords.') }}</p>
          <textarea v-model="batchKeywordsText" class="batch-textarea" rows="12"></textarea>
        </div>
        <template #footer>
          <div class="modal-footer">
            <n-space>
              <n-button @click="showBatchAddModal = false; batchKeywordsText = ''">{{ t('Cancel') }}</n-button>
              <n-button type="primary" @click="batchAddKeywords">{{ t('Add') }}</n-button>
            </n-space>
          </div>
        </template>
      </n-modal>
    </div>
  </div>
</template>

<style scoped>
.field-wrapper { width: 100%; display: flex; flex-direction: column; gap: 6px; }
.field-wrapper.layout-horizontal { flex-direction: row; align-items: flex-start; gap: 12px; }
.field-label { font-weight: 500; color: #374151; font-size: 14px; line-height: 1.5; display: flex; align-items: center; gap: 4px; }
.field-wrapper.layout-horizontal .field-label { min-width: 120px; flex-shrink: 0; margin-top: 8px; }
.required { color: #ef4444; font-weight: bold; }
.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-header label { font-weight: 500; color: #374151; font-size: 14px; line-height: 1.5; }
.seen-by-count { margin: 0 6px; color: #9ca3af; font-size: 12px; }
.table-container { width: 100%; }
.table-grid { width: 100%; }
.table-head { display: flex; background: #fff; border: 1px solid var(--table-border-color, #e5e7eb); border-top-left-radius: 6px; border-top-right-radius: 6px; }
.table-body { border: 1px solid var(--table-border-color, #e5e7eb); border-top: none; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; }
.table-row { display: flex; border-top: 1px solid var(--table-border-color, #e5e7eb); }
.table-cell { padding: 8px 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-left: 1px solid var(--table-border-color, #e5e7eb); }
.table-cell:first-child { border-left: none; }
.table-cell.head { background: #fff; font-weight: 600; }
.table-cell.actions { text-align: center; }
.table-cell.actions .link-btn { margin: 0 2px; }
.table-cell.checkbox { text-align: center; padding: 8px 4px; }
.table-cell.checkbox input[type="checkbox"] { margin: 0; }
.grid-empty { padding: 16px; text-align: center; color: #6b7280; border: 1px dashed #e5e7eb; border-radius: 6px; background: #fff; }
.grid-footer { margin-top: 12px; }
.footer-actions { display: flex; gap: 8px; align-items: center; }
.btn { padding: 6px 12px; border-radius: 6px; cursor: pointer; font-size: 13px; border: 1px solid #e5e7eb; }
.btn-danger { background: #ef4444; color: white; border-color: #ef4444; }
.btn-danger:hover { background: #dc2626; }
.link-btn { background: transparent; border: none; cursor: pointer; padding: 2px; }
.link-btn.edit-btn { color: #6b7280; }
.link-btn.edit-btn:hover { color: #374151; }
.link-btn.delete-btn { color: #ef4444; }
.link-btn.delete-btn:hover { color: #dc2626; }
.child-form-layout { width: 100%; max-height: 60vh; overflow-y: auto; padding: 0; }
.form-tab { width: 100%; }
.form-section { margin-bottom: 32px; }
.form-section:last-child { margin-bottom: 0; }
.section-header { margin-bottom: 20px; padding-bottom: 12px; border-bottom: 2px solid #f3f4f6; }
.section-title { font-size: 18px; font-weight: 600; color: #1f2937; margin: 0; display: flex; align-items: center; gap: 8px; }
.section-body { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; align-items: start; }
.form-column { display: flex; flex-direction: column; gap: 18px; min-width: 0; overflow: hidden; }
.form-field { width: 100%; }
.modal-footer { display: flex; justify-content: flex-end; padding-top: 16px; border-top: 1px solid #f3f4f6; margin-top: 24px; }
.inline-edit-input { width: 100%; border: 1px solid #3b82f6; border-radius: 4px; padding: 4px 8px; font-size: 13px; background: #ffffff; outline: none; box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); }
.cell-display { display: block; width: 100%; min-height: 20px; padding: 2px 4px; word-break: break-word; }
.editable-cell { cursor: pointer; border-radius: 4px; transition: background-color 0.2s ease; }
.editable-cell:hover { background-color: #f3f4f6; border: 1px dashed #d1d5db; padding: 1px 3px; }
.batch-add-content { width: 100%; }
.batch-hint { color: #6b7280; font-size: 13px; margin-bottom: 12px; }
.batch-textarea { width: 100%; border: 1px solid #e5e7eb; border-radius: 6px; padding: 12px; font-size: 14px; line-height: 1.6; resize: vertical; min-height: 200px; font-family: inherit; }
.batch-textarea:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); }
.batch-textarea::placeholder { color: #9ca3af; }
.batch-add-btn { margin-left: 8px; }
.import-btn { margin-left: 8px; }
.hidden-input { display: none; }
.table-cell.head.sortable { cursor: pointer; user-select: none; }
.table-cell.head.sortable:hover { background-color: #f9fafb; }
.sort-label { margin-right: 4px; }
.sort-icon { color: #3b82f6; font-weight: bold; }
.row-count-hint { color: #9ca3af; font-size: 12px; margin-left: auto; white-space: nowrap; }
</style>
