<template>
  <div class="activity-section" v-if="!isNew">
    <!-- 评论/邮件输入 -->
    <div class="comment-input-area">
      <n-input
        v-model:value="commentText"
        type="textarea"
        :placeholder="t('Add a comment')"
        :rows="2"
        :disabled="submitting"
        @keydown.enter.exact="handleAddComment"
      />
      <div class="comment-actions-bar">
        <n-button size="tiny" :disabled="submitting || !commentText.trim()" @click="handleAddComment">
          {{ t('Send') }}
        </n-button>
        <n-button size="tiny" quaternary @click="openNewEmail">
          <template #icon><Icon icon="tabler:mail" :size="14" /></template>
          {{ t('New Email') }}
        </n-button>
      </div>
    </div>

    <!-- Timeline 列表 -->
    <div class="timeline-items" v-if="timelineItems.length > 0">
      <div
        v-for="(item, idx) in timelineItems"
        :key="idx"
        class="timeline-item"
        :data-timestamp="item.creation"
      >
        <div class="timeline-badge" v-if="item.icon">
          <n-icon size="16"><Icon :icon="item.icon" /></n-icon>
        </div>
        <div class="timeline-dot" v-else></div>

        <!-- 普通时间线内容：flex 布局，内容与时间左右排列 -->
        <div v-if="!item.isCard" class="timeline-content">
          <span class="timeline-content-text" v-html="item.content"></span>
          <span v-if="!item.hideTimestamp" class="timeline-time">{{ relativeTime(item.creation) }}</span>
        </div>

        <!-- 评论/通讯卡片：block 布局，2/3 宽度 -->
        <div v-else class="timeline-content is-card">
          <div class="card-header">
            <span class="card-author" v-html="item.cardAuthor || item.content.split(':')[0] + ':'"></span>
            <n-dropdown
              v-if="(item.pagetype === 'Comment' && isCommentOwner(item)) || item.pagetype === 'Communication' || item.pagetype === 'Email'"
              :options="getItemMenuOptions(item)"
              trigger="click"
              @select="(key: string) => handleItemAction(key, item)"
              placement="bottom-end"
            >
              <button class="card-more-btn" @click.stop>
                <n-icon size="16"><Icon icon="tabler:dots" /></n-icon>
              </button>
            </n-dropdown>
          </div>

          <!-- 评论内容 / 编辑模式 -->
          <template v-if="editingCommentName === item.name">
            <div class="card-edit-area">
              <n-input
                v-model:value="editingCommentText"
                type="textarea"
                :rows="2"
                :disabled="savingEdit"
                @keydown.enter.exact="handleSaveEdit"
              />
              <div class="card-edit-actions">
                <n-button size="tiny" :disabled="savingEdit" @click="cancelEdit">{{ t('Cancel') }}</n-button>
                <n-button size="tiny" :loading="savingEdit" :disabled="!editingCommentText.trim()" @click="handleSaveEdit">{{ t('Save') }}</n-button>
              </div>
            </div>
          </template>
          <template v-else>
            <div class="card-body" v-html="item.cardBody || item.content.split(':').slice(1).join(':').trim()"></div>
          </template>

          <div v-if="!item.hideTimestamp" class="timeline-time">{{ relativeTime(item.creation) }}</div>
        </div>
      </div>
    </div>

    <div v-else-if="pageinfoLoaded" class="timeline-empty">
      {{ t('No activity yet') }}
    </div>

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

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import { NButton, NIcon, NInput, NDropdown, useMessage, useDialog, type DropdownOption } from 'naive-ui'
import { Icon } from '@iconify/vue'
import { t } from '@/shared/i18n'
import { useAuthStore } from '@/shared/stores/auth'
import { getPageinfo, addComment, deleteComment, updateComment } from '@/shared/api/timeline'
import EmailComposeModal from '@/shared/components/EmailComposeModal.vue'

interface TimelineItem {
  creation: string
  content: string
  icon?: string
  isCard?: boolean
  hideTimestamp?: boolean
  name?: string
  pagetype?: string
  cardAuthor?: string
  cardBody?: string
  owner?: string
  /** For Communication/Email items: store sender/subject for reply */
  sender?: string
  subject?: string
  recipients?: string
  cc?: string
}

const props = defineProps<{
  entity: string
  id: string
  record: any
  canEdit: boolean
}>()

const emit = defineEmits<{
  refresh: []
}>()

const message = useMessage()
const dialog = useDialog()
const authStore = useAuthStore()

const isNew = computed(() => !props.id || props.id === 'new' || props.id.startsWith('new-'))
const currentUser = computed(() => authStore.user?.username || authStore.user?.name || '')

// ===== Comment (评论) =====
const commentText = ref('')
const submitting = ref(false)

async function handleAddComment(e?: Event) {
  // Enter without Shift submits; Shift+Enter is newline
  if (e instanceof KeyboardEvent && e.shiftKey) return
  if (e) e.preventDefault()

  const text = commentText.value.trim()
  if (!text || submitting.value) return
  submitting.value = true
  try {
    await addComment(props.entity, props.id, text)
    commentText.value = ''
    // Reload pageinfo to show the new comment in timeline
    await loadPageinfo()
    emit('refresh')
  } catch (err: any) {
    message.error(err?.message || t('Failed to add comment'))
  } finally {
    submitting.value = false
  }
}

// ===== Comment Edit / Delete =====
const editingCommentName = ref('')
const editingCommentText = ref('')
const savingEdit = ref(false)

const commentMenuOptions: DropdownOption[] = [
  { label: t('Edit'), key: 'edit' },
  { label: t('Delete'), key: 'delete' },
]

const communicationMenuOptions: DropdownOption[] = [
  { label: t('Reply'), key: 'reply' },
  { label: t('Reply All'), key: 'reply_all' },
]

function getItemMenuOptions(item: TimelineItem): DropdownOption[] {
  if (item.pagetype === 'Communication' || item.pagetype === 'Email') return communicationMenuOptions
  return commentMenuOptions
}

function handleItemAction(key: string, item: TimelineItem) {
  if (key === 'reply' || key === 'reply_all') {
    openReplyEmail(item, key === 'reply_all')
  } else {
    handleCommentAction(key, item)
  }
}

function isCommentOwner(item: TimelineItem): boolean {
  return item.owner === currentUser.value
}

function handleCommentAction(key: string, item: TimelineItem) {
  if (key === 'edit') {
    editingCommentName.value = item.name || ''
    // 提取纯文本内容（去除 HTML 标签）
    const bodyHtml = item.cardBody || ''
    const div = document.createElement('div')
    div.innerHTML = bodyHtml
    editingCommentText.value = div.textContent || div.innerText || ''
  } else if (key === 'delete') {
    dialog.warning({
      title: t('Delete Comment'),
      content: t('Are you sure you want to delete this comment?'),
      positiveText: t('Delete'),
      negativeText: t('Cancel'),
      onPositiveClick: async () => {
        try {
          await deleteComment(item.name!)
          await loadPageinfo()
          emit('refresh')
        } catch (err: any) {
          message.error(err?.message || t('Failed to delete comment'))
        }
      },
    })
  }
}

function cancelEdit() {
  editingCommentName.value = ''
  editingCommentText.value = ''
}

async function handleSaveEdit(e?: Event) {
  if (e instanceof KeyboardEvent && e.shiftKey) return
  if (e) e.preventDefault()

  const text = editingCommentText.value.trim()
  if (!text || savingEdit.value) return
  savingEdit.value = true
  try {
    await updateComment(editingCommentName.value, text)
    editingCommentName.value = ''
    editingCommentText.value = ''
    await loadPageinfo()
    emit('refresh')
  } catch (err: any) {
    message.error(err?.message || t('Failed to update comment'))
  } finally {
    savingEdit.value = false
  }
}

// ===== Timeline =====
const pageinfo = ref<any>(null)
const pageinfoLoaded = ref(false)
const timelineItems = ref<TimelineItem[]>([])

async function loadPageinfo() {
  if (isNew.value) return
  try {
    pageinfo.value = await getPageinfo(props.entity, props.id)
    pageinfoLoaded.value = true
    buildTimelineItems()
  } catch {
    pageinfoLoaded.value = true
  }
}

function buildTimelineItems() {
  const info = pageinfo.value
  if (!info) { timelineItems.value = []; return }

  const items: TimelineItem[] = []

  // 1. Creation message
  if (props.record?.owner && props.record?.creation) {
    const isSelf = props.record.owner === currentUser.value
    items.push({
      creation: props.record.creation,
      content: isSelf
        ? t('You created this')
        : t('{0} created this', [`<strong>${props.record.owner}</strong>`]),
      icon: 'tabler:plus',
    })
  }

  // 2. Modified message (only if different from creation)
  if (props.record?.modified_by && props.record?.modified &&
      props.record.modified !== props.record.creation) {
    const isSelf = props.record.modified_by === currentUser.value
    items.push({
      creation: props.record.modified,
      content: isSelf
        ? t('You last edited this')
        : t('{0} last edited this', [`<strong>${props.record.modified_by}</strong>`]),
      icon: 'tabler:pencil',
    })
  }

  // 3. Comments
  for (const c of info.comments || []) {
    items.push({
      creation: c.creation,
      content: `<strong>${c.owner}</strong>: ${c.content || ''}`,
      icon: 'tabler:message',
      isCard: true,
      name: c.name,
      pagetype: 'Comment',
      cardAuthor: `<strong>${c.owner}</strong>`,
      cardBody: c.content || '',
      owner: c.owner,
    })
  }

  // 4. Communications (includes Email records)
  for (const comm of info.communications || []) {
    const subject = comm.subject || ''
    const sender = comm.sender || ''
    const isEmail = comm.communication_medium === 'Email'
    items.push({
      creation: comm.communication_date || comm.creation,
      content: `<strong>${sender}</strong>: ${subject}`,
      icon: 'tabler:mail',
      isCard: true,
      name: comm.name,
      pagetype: isEmail ? 'Email' : 'Communication',
      sender: comm.sender,
      subject: comm.subject,
      recipients: comm.recipients,
      cc: comm.cc,
    })
  }

  // 5. Assignment logs
  for (const a of info.assignment_logs || []) {
    items.push({
      creation: a.creation,
      content: `<strong>${a.owner}</strong> ${a.content || ''}`,
      icon: 'tabler:user-plus',
    })
  }

  // 6. Attachment logs
  for (const a of info.attachment_logs || []) {
    const isUpload = a.comment_type === 'Attachment'
    const isSelf = a.owner === currentUser.value
    const rawContent = a.content || ''
    // 后端 content 可能自带"已移除"/"Added"等前缀，只提取文件名部分
    const fileName = rawContent.replace(/^(已移除|Added|Removed)\s*/i, '')
    const ownerHtml = `<strong>${a.owner}</strong>`
    const uploadMsg = isSelf
      ? t('You attached {0}', [fileName])
      : t('{0} attached {1}', [ownerHtml, fileName])
    const removeMsg = isSelf
      ? t('You removed attachment {0}', [fileName])
      : t('{0} removed attachment {1}', [ownerHtml, fileName])
    items.push({
      creation: a.creation,
      content: isUpload ? uploadMsg : removeMsg,
      icon: isUpload ? 'tabler:paperclip' : 'tabler:trash',
    })
  }

  // 7. Like logs
  for (const l of info.like_logs || []) {
    const isSelf = l.owner === currentUser.value
    items.push({
      creation: l.creation,
      content: isSelf
        ? t('You Liked')
        : t('{0} Liked', [`<strong>${l.owner}</strong>`]),
      icon: 'tabler:heart',
    })
  }

  // 8. Info logs — Rename/Merge/Restore 前端翻译，Info/Label/Edit 直接使用
  for (const i of info.info_logs || []) {
    const isSelf = i.owner === currentUser.value
    const ownerHtml = `<strong>${i.owner}</strong>`
    // 从后端 content 的 <strong> 标签提取数据值（old/new 名称）
    const vals = [...(i.content || '').matchAll(/<strong>(.*?)<\/strong>/g)].map(m => `<strong>${m[1]}</strong>`)

    let content = `${ownerHtml} ${i.content || ''}`
    let icon = 'tabler:info-circle'

    if (i.comment_type === 'Rename' && vals.length === 2) {
      content = isSelf
        ? t('You renamed from {0} to {1}', vals)
        : t('{0} renamed from {1} to {2}', [ownerHtml, ...vals])
      icon = 'tabler:edit'
    } else if (i.comment_type === 'Merge' && vals.length === 2) {
      content = isSelf
        ? t('You merged {0} into {1}', vals)
        : t('{0} merged {1} into {2}', [ownerHtml, ...vals])
      icon = 'tabler:merge'
    } else if (i.comment_type === 'Restore' && vals.length === 2) {
      content = isSelf
        ? t('You restored {0} as {1}', vals)
        : t('{0} restored {1} as {2}', [ownerHtml, ...vals])
      icon = 'tabler:refresh'
    }

    items.push({ creation: i.creation, content, icon })
  }

  // 9. Workflow logs
  for (const w of info.workflow_logs || []) {
    items.push({
      creation: w.creation,
      content: `<strong>${w.owner}</strong> ${t(w.content || '')}`,
      icon: 'tabler:git-branch',
    })
  }

  // 10. Share logs
  for (const s of info.shared || []) {
    items.push({
      creation: s.creation,
      content: `<strong>${s.owner}</strong> ${s.content || ''}`,
      icon: 'tabler:share',
    })
  }

  // 11. Versions (field changes)
  for (const v of info.versions || []) {
    const isSelf = v.owner === currentUser.value
    items.push({
      creation: v.creation,
      content: isSelf
        ? t('You last edited this')
        : t('{0} last edited this', [`<strong>${v.owner}</strong>`]),
      icon: 'tabler:history',
    })
  }

  // 12. Views
  for (const v of info.views || []) {
    const isSelf = v.owner === currentUser.value
    items.push({
      creation: v.creation,
      content: isSelf
        ? t('You viewed this')
        : t('{0} viewed this', [`<strong>${v.owner}</strong>`]),
      icon: 'tabler:eye',
    })
  }

  // 13. Milestones
  for (const m of info.milestones || []) {
    const field = m.track_field || ''
    const value = m.value || ''
    const isSelf = m.owner === currentUser.value
    const ownerHtml = `<strong>${m.owner}</strong>`
    items.push({
      creation: m.creation,
      content: isSelf
        ? t('You changed {0} to {1}', [field, `<strong>${value}</strong>`])
        : t('{0} changed {1} to {2}', [ownerHtml, field, `<strong>${value}</strong>`]),
      icon: 'tabler:flag',
    })
  }

  // 14. Custom timeline content
  for (const c of info.additional_timeline_content || []) {
    items.push({
      creation: c.creation || '',
      content: c.content || '',
      icon: c.icon || 'tabler:star',
      isCard: c.is_card,
    })
  }

  // Sort by creation desc
  items.sort((a, b) => new Date(b.creation).getTime() - new Date(a.creation).getTime())
  timelineItems.value = items
}

// ===== Relative time =====
function relativeTime(dateStr: string): string {
  if (!dateStr) return ''
  const now = new Date()
  const date = new Date(dateStr)
  const diffMs = now.getTime() - date.getTime()
  const diffSec = Math.floor(diffMs / 1000)
  const diffMin = Math.floor(diffSec / 60)
  const diffHour = Math.floor(diffMin / 60)
  const diffDay = Math.floor(diffHour / 24)
  const diffMonth = Math.floor(diffDay / 30)
  const diffYear = Math.floor(diffDay / 365)

  if (diffSec < 60) return t('just now')
  if (diffMin < 60) return t('{0} minutes ago', [String(diffMin)])
  if (diffHour < 24) return t('{0} hours ago', [String(diffHour)])
  if (diffDay < 30) return t('{0} days ago', [String(diffDay)])
  if (diffMonth < 12) return t('{0} months ago', [String(diffMonth)])
  return t('{0} years ago', [String(diffYear)])
}

// ===== Lifecycle =====
watch(() => [props.entity, props.id], () => {
  if (!isNew.value) {
    loadPageinfo()
  }
}, { immediate: true })

defineExpose({ loadPageinfo })

// ===== Email Compose =====
const emailComposeRef = ref<InstanceType<typeof EmailComposeModal> | null>(null)

function openNewEmail() {
  emailComposeRef.value?.open({
    referencePagetype: props.entity,
    referenceName: props.id,
  })
}

function openReplyEmail(item: TimelineItem, replyAll: boolean) {
  const replyPrefix = 'Re: '
  let subject = item.subject || ''
  if (!subject.startsWith(replyPrefix)) subject = replyPrefix + subject

  const opts: Record<string, any> = {
    referencePagetype: props.entity,
    referenceName: props.id,
    defaultSubject: subject,
    isReply: true,
  }

  if (replyAll && item.recipients) {
    opts.defaultRecipients = item.recipients
    opts.defaultCc = item.cc
  } else if (item.sender) {
    opts.defaultRecipients = item.sender
  }

  emailComposeRef.value?.open(opts)
}

function onEmailSent(_data: any) {
  loadPageinfo()
  emit('refresh')
}
</script>

<style scoped>
.activity-section {
  padding: 20px 0;
}

/* Comment input */
.comment-input-area {
  margin-bottom: 16px;
}

.comment-input-area :deep(.n-input) {
  width: 100%;
}

.comment-actions-bar {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 6px;
}

/* ===== Timeline 时间线 - 现代风格 ===== */
.timeline-items {
  display: flex;
  flex-direction: column;
}

.timeline-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 6px 0;
  position: relative;
}

/* 时间线串联竖线 - 每个 item 左侧有一条竖线连接上下 */
.timeline-item::before {
  content: "";
  position: absolute;
  left: 13px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: #e5e7eb;
}

/* 第一个 item：竖线从图标中心开始 */
.timeline-item:first-child::before {
  top: 20px;
}

/* 最后一个 item：竖线到图标中心结束 */
.timeline-item:last-child::before {
  bottom: calc(100% - 20px);
}

.timeline-badge {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #f3f4f6;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #6b7280;
  position: relative;
  z-index: 1;
  box-shadow: 0 0 0 2px #fff;
}

.timeline-dot {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  position: relative;
  z-index: 1;
}

.timeline-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #d1d5db;
  box-shadow: 0 0 0 2px #fff;
}

/* ===== 普通时间线内容 - flex 布局，内容与时间左右排列有间距 ===== */
.timeline-content {
  flex: 1;
  font-size: 13px;
  color: #374151;
  line-height: 1.6;
  padding: 2px 0;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 12px;
}

.timeline-content-text {
  min-width: 0;
}

.timeline-time {
  color: #9ca3af;
  font-size: 12px;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ===== 评论卡片 - block 布局，2/3 宽度 ===== */
.timeline-content.is-card {
  display: block;
  max-width: 66.67%;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 0;
  overflow: hidden;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  background: #f3f4f6;
  border-bottom: 1px solid #e5e7eb;
}

.card-author {
  font-size: 12px;
  font-weight: 600;
  color: #374151;
}

.card-more-btn {
  width: 24px;
  height: 24px;
  border: none;
  background: transparent;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #9ca3af;
  transition: all 0.15s ease;
}

.card-more-btn:hover {
  background: #e5e7eb;
  color: #374151;
}

.card-body {
  padding: 8px 12px;
  font-size: 13px;
  color: #374151;
  line-height: 1.6;
  word-break: break-word;
}

.card-edit-area {
  padding: 8px 12px;
}

.card-edit-actions {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 6px;
}

/* 卡片内时间戳重置为 block 显示 */
.timeline-content.is-card .timeline-time {
  padding: 6px 12px;
  color: #9ca3af;
  font-size: 11px;
  flex-shrink: unset;
}

.timeline-empty {
  color: #9ca3af;
  font-size: 13px;
  padding: 8px 0;
}
</style>
