<template>
  <div class="email-detail-page">
    <!-- 页面头部 - 工具栏 -->
    <div class="page-header">
      <n-space justify="space-between" align="center">
        <div class="page-header-title-area">
          <template v-if="isEmail && !isNew">
            <span class="page-title page-title-email">{{ record.subject || t('No Subject') }}</span>
            <span v-if="statusBadge" class="status-badge" :class="statusBadge.class">{{ statusBadge.label }}</span>
            <span v-if="deliveryBadge" class="delivery-badge" :class="deliveryBadge.class">{{ deliveryBadge.label }}</span>
          </template>
          <template v-else>
            <span class="page-title">{{ pageTitle }}</span>
          </template>
        </div>
        <component
          v-if="toolbarComponent"
          :is="toolbarComponent"
          :context="toolbarContext"
          :entity="entity"
          :id="id"
          :record="record"
          :can-edit="canEdit"
          :loading="loading"
          :is-submittable="isSubmittable"
          :page-status="pageStatus"
          :sidebar-position="'none'"
          :page-meta="pageMeta"
          @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"
          :loading="loading"
          :is-submittable="isSubmittable"
          :page-status="pageStatus"
          :sidebar-position="'none'"
          :page-meta="pageMeta"
          @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>

    <!-- 信封式沉浸阅读布局 -->
    <div v-if="!initialLoading" class="detail-content-wrapper">
      <!-- ====== Email 模式 ====== -->
      <template v-if="isEmail">
        <EmailEnvelope
          :record="record"
          :attachments="attachments"
          :status-badge="statusBadge"
          :delivery-badge="deliveryBadge"
          @reply="reply"
          @reply-all="replyAll"
          @forward="forward"
          @go-to-reference="goToReference"
        />
      </template>

      <!-- ====== 非 Email 模式：表单降级渲染 ====== -->
      <template v-else>
        <div class="fallback-form-layout">
          <div class="form-layout">
            <div class="form-page">
              <div class="form-tab-content">
                <div class="tab-pane active">
                  <div class="form-sections">
                    <div v-for="section in sections" :key="section.key" class="form-section">
                      <div v-if="section.label" class="section-header">
                        <h4>{{ t(section.label) }}</h4>
                      </div>
                      <div class="section-body">
                        <div v-for="column in section.columns" :key="column.key" class="form-column">
                          <FieldRenderer
                            v-for="field in column.fields"
                            :key="field.fieldname"
                            :df="field"
                            :record="record"
                            :canEdit="canEdit"
                            :ctx="fieldRendererCtx"
                            v-show="shouldShowField(field)"
                          />
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </template>

      <!-- Activity Section: Like + Comment + Timeline -->
      <div class="activity-wrapper">
        <ActivitySection
          :entity="entity"
          :id="id"
          :record="record"
          :can-edit="canEdit"
          @refresh="loadDetail"
        />
      </div>

      <!-- 系统信息页脚 - 仅非 Email 类型显示 -->
      <div v-if="!isEmail" class="meta-footer">
        <div class="meta-item">
          <span class="meta-label">{{ t('Created By') }}</span>
          <span class="meta-value">{{ record.owner || '—' }}</span>
        </div>
        <div class="meta-sep"></div>
        <div class="meta-item">
          <span class="meta-label">{{ t('Created At') }}</span>
          <span class="meta-value">{{ formatDateTime(record.creation) }}</span>
        </div>
        <div class="meta-sep"></div>
        <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>

      <!-- Email Compose Drawer -->
      <EmailComposeModal ref="composeRef" @sent="onEmailSent" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref, shallowRef, markRaw, computed, watch, reactive, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import {
  NButton, NSpace, NIcon,
  useMessage, useDialog,
} from 'naive-ui'
import { Icon } from '@iconify/vue'
import FieldRenderer from '@/core/pagetype/form/FieldRenderer.vue'
import ActivitySection from '@/core/pagetype/form/panel/ActivitySection.vue'
import axios from 'axios'
import { t, createT } from '@/shared/i18n'
import { formatDateTimeInTimezone, formatDateInTimezone, formatTimeInTimezone } 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'
import EmailComposeModal from '@/shared/components/EmailComposeModal.vue'
import EmailEnvelope from '@/shared/components/EmailEnvelope.vue'

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

const { pagetypeSlug, entity } = usePageTypeSlug(route)
const t_ctx = createT(() => entity.value)

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 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 loading = ref(false)
const initialLoading = ref(true)
const isSaving = ref(false)

const isSubmittable = computed(() => !!pageMeta.value?.is_submittable)
const pageStatus = computed(() => record.pagestatus ?? record.pagestatus ?? -1)

const pageTitle = computed(() => {
  if (isNew.value) return t('Create') + ' ' + t(entity.value)
  // Email 模式下标题在模板中直接渲染（主题+badge），这里返回实体名作为降级
  if (isEmail.value) return t(entity.value)
  return record.name || id.value
})

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

// ===== Email is always email in Email PageType =====
const isEmail = computed(() => true)
const isIncoming = computed(() => record.sent_or_received === 'Received')

// ===== Envelope header computed =====
const senderEmail = computed(() => {
  const raw = record.sender || ''
  const match = raw.match(/<(.+?)>/)
  return match ? match[1] : raw
})
const senderFullName = computed(() => {
  const raw = record.sender || ''
  const match = raw.match(/^(.+?)\s*<.*>$/)
  return match ? match[1].trim().replace(/^"|"$/g, '') : ''
})

const attachments = computed(() => record.attachments || [])

// Status & delivery badges
const statusBadge = computed(() => {
  const map: Record<string, { label: string; class: string }> = {
    'Open': { label: t('Open'), class: 'status-open' },
    'Replied': { label: t('Replied'), class: 'status-replied' },
    'Closed': { label: t('Closed'), class: 'status-closed' },
    'Linked': { label: t('Linked'), class: 'status-linked' },
  }
  return map[record.status || ''] || null
})
const deliveryBadge = computed(() => {
  const map: Record<string, { label: string; class: string }> = {
    'Opened': { label: t('Opened'), class: 'delivery-opened' },
    'Bounced': { label: t('Bounced'), class: 'delivery-bounced' },
    'Error': { label: t('Error'), class: 'delivery-error' },
    'Sending': { label: t('Sending'), class: 'delivery-sending' },
    'Scheduled': { label: t('Scheduled'), class: 'delivery-scheduled' },
  }
  return map[record.delivery_status || ''] || null
})

// ===== Email body content =====
const emailBodyRef = ref<HTMLElement | null>(null)
const sanitizedContent = computed(() => record.content || '')

// ===== Toolbar context =====
const toolbarContext = computed(() => ({
  entity: entity.value,
  id: id.value,
  record,
  canEdit: canEdit.value,
  loading: loading.value,
  save: handleSave,
  submit: handleSubmit,
  cancel: handleCancelPg,
  refresh: handleRefresh,
  delete: handleDelete,
  goBack,
  isSubmittable: isSubmittable.value,
  pageStatus: pageStatus.value,
  pageMeta: pageMeta.value,
  rename: handleRename,
  duplicate: handleDuplicate,
  router,
  t: t_ctx,
}))

// ===== Fallback form: sections for non-Email types =====
const sections = computed(() => {
  const orderedFields = getOrderedFields()
  const result: any[] = []
  let currentSection: any = { key: 'default', label: '', columns: [] }
  let currentColumn: any = { key: 'default', fields: [] }

  for (const field of orderedFields) {
    if (field.fieldtype === 'Section Break') {
      if (field.hidden) continue
      if (currentColumn.fields.length > 0) currentSection.columns.push({ ...currentColumn })
      if (currentSection.columns.length > 0) result.push({ ...currentSection })
      currentSection = { key: field.fieldname || `section_${result.length}`, label: field.label || '', columns: [] }
      currentColumn = { key: 'default', fields: [] }
    } else if (field.fieldtype === 'Column Break') {
      if (currentColumn.fields.length > 0) currentSection.columns.push({ ...currentColumn })
      currentColumn = { key: `column_${currentSection.columns.length}`, fields: [] }
    } else if (field.fieldtype === 'Tab Break') {
      // Skip tab breaks in fallback
      continue
    } else {
      currentColumn.fields.push(field)
    }
  }
  if (currentColumn.fields.length > 0) currentSection.columns.push({ ...currentColumn })
  if (currentSection.columns.length > 0) result.push({ ...currentSection })
  return result
})

// Field change plugin trigger (created once, not inside computed)
const onFieldChange = createFieldChangeTrigger(entity.value, record)

const fieldRendererCtx = computed(() => ({
  t: t_ctx,
  getSelectOptions,
  toDateValue,
  updateDateValue,
  handleButtonClick: (_field: any) => {},
  getJsonDisplayValue,
  updateJsonValue,
  formatJson,
  entity: entity.value,
  id: id.value,
  reload: async () => { await loadDetail() },
  save: handleSave,
  saveSilent: () => handleSave({ silent: true }),
  seenByExpanded: false,
  toggleSeenBy: () => {},
  seenByUsers: [],
  onFieldChange,
}))

// ===== Helper functions =====
function splitEmailList(str: string): string[] {
  if (!str) return []
  return str.split(/[;,]/).map(s => s.trim()).filter(Boolean)
}

function formatDate(value: any): string {
  if (!value) return '—'
  try {
    return formatDateInTimezone(value)
  } catch { return String(value) }
}

function formatTime(value: any): string {
  if (!value) return ''
  try {
    return formatTimeInTimezone(value)
  } catch { return '' }
}

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

// ===== Navigation =====
function goBack() {
  const listPage = history.state?._listPage || 1
  router.push({
    name: 'PageTypeList',
    params: { entity: pagetypeSlug.value },
    query: listPage > 1 ? { page: listPage } : {}
  })
}

function goToReference() {
  if (!record.reference_pagetype || !record.reference_name) return
  router.push({
    name: 'PageTypeDetail',
    params: {
      entity: record.reference_pagetype.replace(/ /g, '-').toLowerCase(),
      id: record.reference_name,
    }
  })
}

// ===== Email actions =====
const composeRef = ref<InstanceType<typeof EmailComposeModal> | null>(null)
const emailAccount = computed(() => record.email_account || '')

function getSenderEmailId(): string {
  const bootAccounts = (window as any).jingrow?.boot?.email_accounts || []
  for (const account of bootAccounts) {
    if (account.email_account === emailAccount.value) return account.email_id || ''
  }
  return ''
}

function getMailArgs() {
  return {
    pg: record,
    lastEmail: record,
    sender: getSenderEmailId(),
    attachments: attachments.value,
    referencePagetype: record.reference_pagetype,
    referenceName: record.reference_name,
  }
}

function reply() {
  composeRef.value?.open({
    ...getMailArgs(),
    isReply: true,
    replyAll: false,
    defaultSubject: (record.subject || '').startsWith('Re:') ? record.subject : `Re: ${record.subject}`,
    defaultRecipients: record.sender || '',
    defaultContent: record.content || '',
  })
}

function replyAll() {
  const selfEmail = getSenderEmailId()
  const allRecipients = splitEmailList(record.recipients || '')
  const allCc = splitEmailList(record.cc || '')
  const otherRecipients = [...allRecipients, ...allCc].filter(e => e !== selfEmail)
  composeRef.value?.open({
    ...getMailArgs(),
    isReply: true,
    replyAll: true,
    defaultSubject: (record.subject || '').startsWith('Re:') ? record.subject : `Re: ${record.subject}`,
    defaultRecipients: record.sender || '',
    defaultCc: otherRecipients.join(', '),
    defaultContent: record.content || '',
  })
}

function forward() {
  composeRef.value?.open({
    ...getMailArgs(),
    isForward: true,
    defaultSubject: (record.subject || '').startsWith('Fw:') ? record.subject : `Fw: ${record.subject}`,
    defaultRecipients: '',
    defaultContent: record.content || '',
  })
}

function onEmailSent() {
  loadDetail()
}

// ===== CRUD operations (mirrored from default.vue) =====
async function loadMeta() {
  loading.value = true
  try {
    const result = await getPageTypeMeta(entity.value)
    if (result.success && result.data) {
      metaFields.value = result.data.fields || []
      pageMeta.value = result.data || {}
      if (pageMeta.value.is_virtual) canEdit.value = false
      else canEdit.value = permissionStore.canWrite(entity.value)
    } else {
      message.error(result.message || t('Failed to load metadata'))
    }
  } catch (error) {
    message.error(t('Failed to load metadata'))
  } finally {
    loading.value = false
  }
}

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(':')) continue
    else if (field.fieldtype === 'Check') value = defaultVal === '1' ? 1 : 0
    else if (field.fieldtype === 'Select' && defaultVal) value = defaultVal
    else value = field.default
    if (value !== undefined && record[field.fieldname] === undefined) record[field.fieldname] = value
  }
}

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())
      }
    }
  }
}

const dynamicFieldOptions = ref<Record<string, string[]>>({})

function getSelectOptions(field: any) {
  if (dynamicFieldOptions.value[field.fieldname]) {
    return dynamicFieldOptions.value[field.fieldname].map((opt: string) => ({ label: t_ctx(opt), value: opt }))
  }
  if (!field.options) return []
  return field.options.split('\n').filter((s: string) => s.trim() !== '').map((opt: string) => ({ label: t_ctx(opt), value: opt }))
}

function toDateValue(v: any): number | null {
  if (!v) return null
  if (typeof v === 'number') return v
  if (v instanceof Date) return v.getTime()
  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; return }
  const d = new Date(v)
  record[fieldname] = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}

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

function getJsonDisplayValue(value: any) {
  if (!value) return ''
  if (typeof value === 'string') {
    try { return JSON.stringify(JSON.parse(value), null, 2) } catch { return value }
  }
  try { return JSON.stringify(value, null, 2) } catch { return String(value) }
}

function updateJsonValue(fieldName: string, value: string) {
  if (!value.trim()) { record[fieldName] = null; return }
  try { record[fieldName] = JSON.parse(value) } catch { record[fieldName] = value }
}

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'))) {
    orderedFields.push({ fieldname: '__newname', fieldtype: 'Data', label: 'Name', reqd: 1, placeholder: 'Enter document name' })
  }
  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))
    const orderedFieldnames = new Set(pageMeta.value.field_order)
    const remaining = metaFields.value.filter((f: any) => !orderedFieldnames.has(f.fieldname))
    orderedFields = [...orderedFields, ...ordered, ...remaining]
  } else {
    orderedFields = [...orderedFields, ...metaFields.value]
  }
  return orderedFields
}

function evaluateDependsOn(expression: string) {
  if (!expression) return true
  try {
    if (expression.startsWith('eval:')) {
      const code = expression.substring(5)
      return !!(new Function('pg', `return !!(${code})`)(record))
    }
    return !!record[expression]
  } catch {
    if (expression.startsWith('eval:')) return false
    return true
  }
}

function shouldShowField(field: any) {
  if (['Tab Break', 'Section Break', 'Column Break'].includes(field.fieldtype)) return false
  if (field && (field.hidden === 1 || field.hidden === true || field.hidden === '1')) return false
  if (!field.depends_on) return true
  return evaluateDependsOn(field.depends_on)
}

async function loadDetail() {
  if (isNew.value) {
    Object.keys(record).forEach(k => delete record[k])
    originalRecord.value = {}
    applyDefaultValues()
    await triggerRecordInit(entity.value, record)
    await applyFieldConfig()
    const storageKey = `duplicate:${entity.value}`
    try {
      const stored = sessionStorage.getItem(storageKey)
      if (stored) {
        sessionStorage.removeItem(storageKey)
        Object.assign(record, JSON.parse(stored))
      }
    } catch {}
    return
  }
  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 的字段，undefined 导致控件保留旧值
      for (const field of metaFields.value) {
        if (record[field.fieldname] === undefined) {
          record[field.fieldname] = null
        }
      }
      if (attachmentsRes.success && attachmentsRes.data) record.attachments = attachmentsRes.data
      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])
    }
    await applyFieldConfig()
  } catch (error) {
    message.error(t('Failed to load detail'))
    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
  window.dispatchEvent(new CustomEvent('sync-form-builder-fields'))
  await new Promise(resolve => requestAnimationFrame(resolve))
  try {
    if (JSON.stringify(record) === JSON.stringify(originalRecord.value)) {
      message.info(t('No changes to save'))
      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 dataToSend = { ...record }
      if (typeof dataToSend.fields === 'string') { try { dataToSend.fields = JSON.parse(dataToSend.fields) } catch {} }
      const res = await updateRecord(entity.value, id.value, dataToSend)
      if (res.success) {
        if (!silent) message.success(t('Saved successfully'))
        try { originalRecord.value = JSON.parse(JSON.stringify(record)) } catch { originalRecord.value = { ...record } }
        await loadDetail()
        isSaving.value = false
      } else {
        message.error(res.message || t('Save failed'))
        isSaving.value = false
      }
    }
  } catch (error) {
    message.error(t('Save failed'))
    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')) } 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')) } finally { loading.value = false }
}

function handleKeydownSave(e: KeyboardEvent) {
  if ((e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'S')) {
    e.preventDefault()
    if (canEdit.value && !loading.value) handleSave()
  }
}

async function handleRefresh() {
  if (loading.value || isNew.value) return
  try { await loadDetail() } catch { message.error(t('Failed to refresh')) }
}

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 { message.error(t('Failed to delete')) } finally { loading.value = false }
    }
  })
}

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

function handleDuplicate(_newName: string) {
  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 } })
}

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 })
      await Promise.all(Array.from(files).map(file => uploadAttachment(file, entity.value, id.value, false)))
      message.destroyAll()
      message.success(t('Attachments uploaded successfully'))
      await loadDetail()
    } catch (error: any) {
      message.destroyAll()
      message.error(error.message || t('Failed to upload attachment'))
    }
  }
  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 { message.error(t('Failed to delete attachment')) }
}

// ===== Realtime =====
const realtime = useRealtime()
function handlePgUpdate(data: PgUpdateData) {
  if (isSaving.value) return
  if (data.pagetype !== entity.value || data.name !== id.value) return
  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 {}
  loadDetail()
}

// ===== Lifecycle =====
onMounted(async () => {
  await loadAllPlugins()
  window.addEventListener('keydown', handleKeydownSave, { capture: true })
  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(() => {
  window.removeEventListener('keydown', handleKeydownSave, { capture: true } as any)
})

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
    // When entity changes away from Email, this custom override component
    // will be replaced by DetailPage's resolver. Don't process the new entity here,
    // otherwise this component's loadDetail() will consume sessionStorage data
    // (e.g. duplicate:Contact) meant for the target page.
    if (entityChanged) return
    if (idChanged) {
      await loadDetail()
      if (!isNew.value && String(newVal.id)) {
        realtime.watchDocument(entity.value, String(newVal.id), { onUpdate: handlePgUpdate })
      }
    }
  }
)
</script>

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

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

.page-header-title-area {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1;
}

.page-title {
  font-size: 16px;
  font-weight: 500;
  color: #6b7280;
}

.page-title-email {
  font-size: 16px;
  font-weight: 600;
  color: #111827;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.page-description {
  font-size: 13px;
  color: #9ca3af;
}

/* ====== Detail Content Wrapper ====== */
.detail-content-wrapper {
  --envelope-px: 32px;
}

/* Status & Delivery badges (used in page header) */
.status-badge, .delivery-badge {
  font-size: 11px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 12px;
  white-space: nowrap;
  flex-shrink: 0;
}
.status-badge.status-open { background: #dbeafe; color: #1d4ed8; }
.status-badge.status-replied { background: #d1fae5; color: #065f46; }
.status-badge.status-closed { background: #f3f4f6; color: #6b7280; }
.status-badge.status-linked { background: #ede9fe; color: #5b21b6; }
.delivery-badge.delivery-opened { background: #d1fae5; color: #065f46; }
.delivery-badge.delivery-bounced { background: #fee2e2; color: #991b1b; }
.delivery-badge.delivery-error { background: #fee2e2; color: #991b1b; }
.delivery-badge.delivery-sending { background: #fef3c7; color: #92400e; }
.delivery-badge.delivery-scheduled { background: #e0e7ff; color: #3730a3; }

/* ====== Fallback form for non-Email types ====== */
.fallback-form-layout {
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  overflow: hidden;
  padding: 28px var(--envelope-px) 20px;
}

.form-layout {
  background: #ffffff;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
}

.form-page {
  padding: 24px var(--envelope-px);
}

.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;
}

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

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

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

/* ====== Activity & Meta ====== */
.activity-wrapper {
  padding: 0 var(--envelope-px);
  margin-top: 24px;
}

.meta-footer {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px var(--envelope-px) 20px;
  color: #6b7280;
  font-size: 13px;
  border-top: 1px solid #f0f0f0;
  margin-top: 24px;
}

.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;
}

/* ====== Layout ====== */
.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); } }

.email-detail-page { overflow: visible !important; }

/* ====== Responsive ====== */
@media (max-width: 768px) {
  .email-detail-page { padding: 8px; }
  .page-header { margin-bottom: 16px; }
  .page-title { font-size: 14px; }
  .detail-content-wrapper { --envelope-px: 16px; }
  .meta-footer { padding-top: 12px; padding-bottom: 16px; flex-wrap: wrap; }
}

@media (min-width: 769px) and (max-width: 1024px) {
  .email-detail-page { padding: 12px; }
  .detail-content-wrapper { --envelope-px: 24px; }
}
</style>
