<template>
  <n-drawer v-model:show="visible" :width="'50%'" placement="right" :mask-closable="false">
    <n-drawer-content :title="t('New Email')" closable>
      <div class="email-compose">
        <!-- Sender (From) -->
        <div v-if="senderOptions.length > 1" class="compose-field">
          <label class="field-label">{{ t('From') }}</label>
          <n-select
            v-model:value="form.sender"
            :options="senderOptions"
            size="small"
            @update:value="onSenderChange"
          />
        </div>

        <!-- Recipients (To) -->
        <div class="compose-field">
          <label class="field-label">
            {{ t('To') }}
            <button class="toggle-cc-bcc" @click="showCcBcc = !showCcBcc">
              {{ showCcBcc ? t('Hide') : t('CC') + ' / ' + t('BCC') }}
            </button>
          </label>
          <n-select
            v-model:value="form.recipients"
            filterable
            multiple
            tag
            :loading="searchingContacts"
            :options="contactOptions"
            :placeholder="''"
            @search="onContactSearch"
            size="small"
          />
        </div>

        <!-- CC -->
        <div v-if="showCcBcc" class="compose-field">
          <label class="field-label">{{ t('CC') }}</label>
          <n-select
            v-model:value="form.cc"
            filterable
            multiple
            tag
            :loading="searchingContacts"
            :options="contactOptions"
            :placeholder="''"
            @search="onContactSearch"
            size="small"
          />
        </div>

        <!-- BCC -->
        <div v-if="showCcBcc" class="compose-field">
          <label class="field-label">{{ t('BCC') }}</label>
          <n-select
            v-model:value="form.bcc"
            filterable
            multiple
            tag
            :loading="searchingContacts"
            :options="contactOptions"
            :placeholder="''"
            @search="onContactSearch"
            size="small"
          />
        </div>

        <!-- Subject -->
        <div class="compose-field">
          <label class="field-label">
            {{ t('Subject') }}
            <span class="required">*</span>
          </label>
          <n-input
            v-model:value="form.subject"
            :placeholder="''"
            size="small"
          />
        </div>

        <!-- Email Template -->
        <div class="compose-field">
          <LinkField
            v-model="form.emailTemplate"
            :options="'Email Template'"
            :label="t('Email Template')"
            :enable-create="true"
            @create="onCreateTemplate"
            @update:model-value="onTemplateChange"
          />
        </div>

        <!-- Rich Text Body -->
        <div class="compose-field compose-body">
          <div class="message-editor-wrapper">
            <Jeditor
              v-model="editorContent"
              :df="{ fieldname: 'message', fieldtype: 'Jeditor', label: t('Message') }"
              :disabled="false"
            />
          </div>
        </div>

        <!-- Existing Document Attachments -->
        <div v-if="existingAttachments.length" class="compose-field">
          <label class="field-label">{{ t('Document Attachments') }}</label>
          <div class="existing-attach-list">
            <div v-for="att in existingAttachments" :key="att.name" class="existing-attach-row">
              <n-checkbox :checked="selectedExistingAttachments.includes(att.name)" @update:checked="toggleExistingAttachment(att.name)" size="small" />
              <span class="att-file-name">{{ att.file_name || att.name }}</span>
              <a v-if="att.file_url" :href="att.file_url" target="_blank" class="att-link">
                <Icon icon="tabler:external-link" :size="12" />
              </a>
            </div>
          </div>
        </div>

        <!-- New Attachments -->
        <div class="compose-field">
          <label class="field-label">{{ t('Attachments') }}</label>
          <div class="attachment-area">
            <div v-for="(file, idx) in attachedFiles" :key="idx" class="attached-file">
              <Icon icon="tabler:paperclip" :size="14" />
              <span class="file-name">{{ file.name }}</span>
              <button class="remove-file" @click="removeAttachment(idx)">
                <Icon icon="tabler:x" :size="14" />
              </button>
            </div>
            <button class="add-attachment-btn" @click="pickAttachments">
              <Icon icon="tabler:plus" :size="14" />
              {{ t('Add Attachment') }}
            </button>
            <input ref="fileInputRef" type="file" multiple style="display: none" @change="onFileSelected" />
          </div>
        </div>

        <!-- Options row -->
        <div class="compose-options">
          <n-checkbox v-model:checked="form.sendMeCopy" size="small">
            {{ t('Send me a copy') }}
          </n-checkbox>
          <n-checkbox v-model:checked="form.readReceipt" size="small">
            {{ t('Send Read Receipt') }}
          </n-checkbox>
        </div>

        <!-- Schedule Send -->
        <div class="compose-field">
          <label class="field-label">{{ t('Schedule Send') }}</label>
          <n-date-picker
            v-model:value="form.sendAfter"
            type="datetime"
            clearable
            size="small"
            :placeholder="''"
          />
        </div>
      </div>

      <template #footer>
        <div class="compose-footer">
          <n-button @click="discard">{{ t('Discard') }}</n-button>
          <n-button
            :loading="savingDraft"
            @click="saveAsDraft"
            class="draft-btn"
          >
            <template #icon><Icon icon="tabler:file-pencil" :size="16" /></template>
            {{ t('Save Draft') }}
          </n-button>
          <n-button
            type="primary"
            :loading="sending"
            @click="sendEmail"
            class="send-btn-brand"
          >
            <template #icon><Icon icon="tabler:send" :size="16" /></template>
            {{ t('Send') }}
          </n-button>
        </div>
      </template>
    </n-drawer-content>
  </n-drawer>
</template>

<script setup lang="ts">
import { ref, reactive, computed, nextTick, watch } from 'vue'
import { NDrawer, NDrawerContent, NSelect, NInput, NButton, NCheckbox, NDatePicker, useMessage } from 'naive-ui'
import { Icon } from '@iconify/vue'
import { api } from '@/shared/api/common'
import { t } from '@/shared/i18n'
import LinkField from '@/shared/components/LinkField.vue'
import Jeditor from '@/core/pagetype/form/controls/Jeditor.vue'

// -------------------------------------------------------
// Public API
// -------------------------------------------------------
const visible = ref(false)
const sending = ref(false)
const savingDraft = ref(false)

const props = defineProps<{
  /** Reference document for template rendering and subject auto-fill */
  pg?: Record<string, any>
  /** Reference document metadata */
  referencePagetype?: string
  referenceName?: string
  /** Pre-fill recipients (e.g. from a Contact/Lead) */
  defaultRecipients?: string
  defaultCc?: string
  defaultBcc?: string
  /** Pre-fill subject (e.g. for replies) */
  defaultSubject?: string
  /** Pre-fill body (e.g. for replies / templates) */
  defaultContent?: string
  isReply?: boolean
  replyAll?: boolean
  /** Last email data for reply logic */
  lastEmail?: Record<string, any>
  /** Is this a forwarded email? */
  isForward?: boolean
  /** Is this editing an existing email? */
  isEdit?: boolean
}>()

const emit = defineEmits<{
  (e: 'sent', data: any): void
  (e: 'discard'): void
}>()

// Expose open/close for parent components
function open(opts?: Partial<typeof props>) {
  // Reset form
  resetForm()
  // Reset propsRef from previous call
  Object.keys(propsRef).forEach(k => delete propsRef[k])
  // Apply opts
  if (opts) Object.assign(propsRef, opts)
  // Pre-fill recipients
  if (propsRef.defaultRecipients) form.recipients = splitEmailList(propsRef.defaultRecipients)
  if (propsRef.defaultCc) form.cc = splitEmailList(propsRef.defaultCc)
  if (propsRef.defaultBcc) form.bcc = splitEmailList(propsRef.defaultBcc)
  if (propsRef.defaultSubject) form.subject = propsRef.defaultSubject
  // For edit mode: set sender from opts
  if (propsRef.sender) form.sender = propsRef.sender
  // For edit mode: show CC/BCC if they have values
  if (propsRef.defaultCc || propsRef.defaultBcc) showCcBcc.value = true
  // Smart reply recipient logic
  setupReplyRecipients()
  // Auto-fill subject from document
  if (!form.subject && propsRef.referencePagetype && propsRef.referenceName) {
    autoFillSubject()
  }
  visible.value = true
  nextTick(async () => {
    // For edit mode: set content directly from the existing email
    if (propsRef.isEdit) {
      const content = propsRef.lastEmail?.content || propsRef.defaultContent || ''
      if (content) {
        editorContent.value = content
      }
    }
    // Append email signature
    await appendSignature()
    // Append reply quoting
    if (propsRef.isEdit) {
      // Edit mode: content already set above, skip quote/draft
    } else if (propsRef.isReply && propsRef.lastEmail) {
      appendReplyQuote()
    } else if (propsRef.isForward && propsRef.lastEmail) {
      appendForwardQuote()
    }
    // Restore draft if available (only for new emails, not replies/forwards/edits)
    if (!propsRef.isReply && !propsRef.isForward && !propsRef.isEdit) {
      await restoreDraft()
    }
    // Load existing attachments from reference document
    loadExistingAttachments()
  })
}

function close() {
  saveDraft() // Save draft before closing
  visible.value = false
}

// Internal props ref (mutable copy for open())
const propsRef = reactive<Record<string, any>>({})

defineExpose({ open, close, visible })

// -------------------------------------------------------
// Form state
// -------------------------------------------------------
const showCcBcc = ref(false)
const editorContent = ref('')
const form = reactive({
  sender: '',
  recipients: [] as string[],
  cc: [] as string[],
  bcc: [] as string[],
  subject: '',
  emailTemplate: '' as string,
  sendMeCopy: false,
  readReceipt: false,
  sendAfter: null as number | null, // timestamp for scheduled send
})

const attachedFiles = ref<File[]>([])

function resetForm() {
  form.sender = defaultSender.value
  form.recipients = []
  form.cc = []
  form.bcc = []
  form.subject = ''
  form.emailTemplate = ''
  form.sendMeCopy = !!(window as any).jingrow?.boot?.user?.send_me_a_copy
  form.readReceipt = false
  form.sendAfter = null
  attachedFiles.value = []
  existingAttachments.value = []
  selectedExistingAttachments.value = []
  showCcBcc.value = false
  signatureLoaded.value = false
  replyQuoteAdded.value = false
  editorContent.value = ''
}

// -------------------------------------------------------
// Sender options (from boot.email_accounts)
// -------------------------------------------------------
const senderOptions = computed(() => {
  const boot = (window as any).jingrow?.boot
  if (!boot?.email_accounts?.length) return []
  return boot.email_accounts
    .filter((a: any) =>
      !['All Accounts', 'Sent', 'Spam', 'Trash'].includes(a.email_account) &&
      a.enable_outgoing
    )
    .map((a: any) => ({ label: a.email_id, value: a.email_id }))
})

const defaultSender = computed(() => {
  if (senderOptions.value.length === 1) return senderOptions.value[0].value
  const user = (window as any).jingrow?.boot?.user?.email
  if (user && senderOptions.value.find(s => s.value === user)) return user
  return senderOptions.value[0]?.value || ''
})

// -------------------------------------------------------
// Email Signature
// -------------------------------------------------------
const signatureLoaded = ref(false)
const currentSignature = ref('')

async function fetchSignature(senderEmail?: string) {
  const bootUser = (window as any).jingrow?.boot?.user
  // Try user boot signature first
  if (bootUser?.email_signature && !senderEmail) {
    let sig = bootUser.email_signature
    if (sig && !isHtml(sig)) sig = sig.replace(/\n/g, '<br>')
    return '<br>' + sig
  }
  // Fetch from Email Account
  try {
    const filters: Record<string, any> = { add_signature: 1 }
    if (senderEmail) filters.email_id = senderEmail
    else filters.default_outgoing = 1
    const res = await api.call('jingrow.client.get_list', {
      pagetype: 'Email Account',
      fields: ['signature', 'email_id'],
      filters: JSON.stringify(filters),
      limit_page_length: 1,
    })
    const data = res?.message ?? res
    if (Array.isArray(data) && data.length && data[0].signature) {
      let sig = data[0].signature
      if (!isHtml(sig)) sig = sig.replace(/\n/g, '<br>')
      return '<br>' + sig
    }
  } catch { /* ignore */ }
  return ''
}

async function appendSignature() {
  if (signatureLoaded.value) return
  const sig = await fetchSignature(form.sender)
  if (sig) {
    currentSignature.value = sig
    signatureLoaded.value = true
    // Append signature to editor
    const currentHtml = editorContent.value
    if (currentHtml && !stripHtml(currentHtml).includes(stripHtml(sig))) {
      editorContent.value = currentHtml + sig
    } else if (!currentHtml) {
      editorContent.value = sig
    }
  }
}

function onSenderChange(newSender: string) {
  // Re-append signature for new sender
  if (signatureLoaded.value && currentSignature.value) {
    // Remove old signature first
    const html = editorContent.value
    const sigHtml = stripHtml(currentSignature.value)
    if (html) {
      const plain = stripHtml(html)
      if (plain.includes(sigHtml)) {
        editorContent.value = html.replace(currentSignature.value, '')
      }
    }
  }
  signatureLoaded.value = false
  currentSignature.value = ''
  nextTick(appendSignature)
}

function isHtml(str: string): boolean {
  return /<[a-z][\s\S]*>/i.test(str)
}

function stripHtml(html: string): string {
  return html.replace(/<[^>]*>/g, '').replace(/\s+/g, ' ').trim()
}

// -------------------------------------------------------
// Contact search (for To/CC/BCC autocomplete)
// -------------------------------------------------------
const searchingContacts = ref(false)
const contactOptions = ref<{ label: string; value: string }[]>([])

let searchTimer: ReturnType<typeof setTimeout> | null = null

async function onContactSearch(query: string) {
  if (searchTimer) clearTimeout(searchTimer)
  if (!query || query.length < 2) {
    contactOptions.value = []
    return
  }
  searchTimer = setTimeout(async () => {
    searchingContacts.value = true
    try {
      const res = await api.call('jingrow.email.get_contact_list', { txt: query })
      const data = res?.message ?? res
      if (Array.isArray(data)) {
        contactOptions.value = data.map((d: any) => ({
          label: d.label || d.value,
          value: d.value || d.label,
        }))
      }
    } catch {
      contactOptions.value = []
    } finally {
      searchingContacts.value = false
    }
  }, 300)
}

// -------------------------------------------------------
// Email Templates (via LinkField)
// -------------------------------------------------------

function onCreateTemplate() {
  window.open('/app/email-template/new-email-template', '_blank')
}

async function fetchTemplateContent(templateName: string) {
  if (!templateName) return null
  try {
    // Build pg (document) for template rendering
    let pg: Record<string, any> = {}
    if (propsRef.referencePagetype && propsRef.referenceName) {
      pg = { pagetype: propsRef.referencePagetype, name: propsRef.referenceName }
    }
    const res = await api.call('jingrow.email.pagetype.email_template.email_template.get_email_template', {
      template_name: templateName,
      pg: JSON.stringify(pg),
    })
    return res?.message ?? res
  } catch (err) {
    console.error('[EmailCompose] Failed to load template:', err)
    return null
  }
}

async function onTemplateChange(templateName: string) {
  if (!templateName) return
  const data = await fetchTemplateContent(templateName)
  if (!data) return
  if (data.subject) form.subject = data.subject
  if (data.message) editorContent.value = data.message
}

// -------------------------------------------------------
// Reply logic (smart recipients + quoted original)
// -------------------------------------------------------
const replyQuoteAdded = ref(false)

function setupReplyRecipients() {
  if (!propsRef.isReply || !propsRef.lastEmail) return
  const lastEmail = propsRef.lastEmail
  const sender = form.sender
  const lastSender = (lastEmail.sender || '').replace(/<.*>/, '').trim() || lastEmail.sender

  // If replying to own email, set recipients to original recipients
  if (lastSender === sender || lastEmail.sender === sender) {
    if (!form.recipients.length) {
      form.recipients = splitEmailList(lastEmail.recipients)
    }
    if (propsRef.replyAll) {
      if (!form.cc.length) form.cc = splitEmailList(lastEmail.cc)
      if (!form.bcc.length) form.bcc = splitEmailList(lastEmail.bcc)
    }
  } else {
    // Replying to someone else's email
    if (!form.recipients.length) {
      form.recipients = [lastEmail.sender || lastSender]
    }
    if (propsRef.replyAll) {
      // Add original recipients (minus self) to CC
      const originalRecipients = splitEmailList(lastEmail.recipients)
      const originalCc = splitEmailList(lastEmail.cc)
      const selfEmail = sender
      const newCc = [...originalRecipients, ...originalCc].filter(
        (e: string) => e !== selfEmail && !form.recipients.includes(e)
      )
      if (!form.cc.length) form.cc = newCc
    }
  }
  // Auto-show CC/BCC if there are CC/BCC values
  if (form.cc.length || form.bcc.length) showCcBcc.value = true
}

function appendReplyQuote() {
  if (replyQuoteAdded.value) return
  const lastEmail = propsRef.lastEmail
  if (!lastEmail) return

  let content = lastEmail.original_comment || lastEmail.content || ''
  if (!content || content.trim() === '') return

  const date = formatRfc5322Date(lastEmail.communication_date || lastEmail.creation || '')
  const senderName = lastEmail.sender || ''
  const subject = lastEmail.subject || ''

  // Clean quoted content: strip scripts/styles, remove inline styles, strip head/meta/title
  content = cleanupQuotedContent(content)

  // Normalize image src to absolute URLs
  content = fixImageUrls(content)

  const recipients = lastEmail.recipients || ''
  const replyHeader = `<p class="cursor-space"></p><p class="reply-original">------- Original Message -------</p><div class="quote-header"><p>From: ${escapeHtml(senderName)}<br>To: ${escapeHtml(recipients)}<br>Date: ${escapeHtml(date)}<br>Subject: ${escapeHtml(subject)}</p></div>`

  const current = editorContent.value
  editorContent.value = (current || '') + replyHeader + `<blockquote>${content}</blockquote>`
  replyQuoteAdded.value = true
}

function appendForwardQuote() {
  if (replyQuoteAdded.value) return
  const lastEmail = propsRef.lastEmail
  if (!lastEmail) return

  let content = lastEmail.original_comment || lastEmail.content || ''
  if (!content || content.trim() === '') return

  const date = formatRfc5322Date(lastEmail.communication_date || lastEmail.creation || '')
  const senderName = lastEmail.sender || ''
  const subject = lastEmail.subject || ''

  // Clean quoted content: strip scripts/styles, remove inline styles, strip head/meta/title
  content = cleanupQuotedContent(content)

  // Normalize image src to absolute URLs
  content = fixImageUrls(content)

  const recipients = lastEmail.recipients || ''
  const cc = lastEmail.cc || ''
  const forwardHeader = `<p class="cursor-space"></p><p class="reply-original">------- Forwarded Message -------</p><div class="quote-header"><p>From: ${escapeHtml(senderName)}<br>To: ${escapeHtml(recipients)}<br>Date: ${escapeHtml(date)}<br>Subject: ${escapeHtml(subject)}</p></div>`

  const current = editorContent.value
  editorContent.value = (current || '') + forwardHeader + `<blockquote>${content}</blockquote>`
  replyQuoteAdded.value = true
}

function formatRfc5322Date(dateStr: string): string {
  if (!dateStr) return ''
  try {
    const d = new Date(dateStr)
    const locale = getCurrentLocale()
    return new Intl.DateTimeFormat(locale, {
      weekday: 'short',
      year: 'numeric',
      month: 'short',
      day: 'numeric',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      timeZoneName: 'short',
    }).format(d)
  } catch {
    return dateStr
  }
}

function escapeHtml(str: string): string {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
}

function fixImageUrls(html: string): string {
  // Convert relative image src to absolute URLs
  const base = window.location.origin
  return html.replace(/<img([^>]*?)src=["']([^"']*?)["']([^>]*?)>/gi, (match, before, src, after) => {
    if (src.startsWith('https://') || src.startsWith('http://') || src.startsWith('//') || src.startsWith('data:')) {
      return match
    }
    const absolute = src.startsWith('/') ? base + src : base + '/' + src
    return `<img${before}src="${absolute}"${after}>`
  })
}

/**
 * Clean up quoted email content:
 * 1. Parse via DOMParser to extract body (strips <head>, <meta>, <title>, etc.)
 * 2. Remove dangerous/irrelevant tags: script, style, noscript, title, link
 * 3. Remove all inline style attributes (so original bold/font-size doesn't leak)
 * 4. Remove tracking pixels (1x1 transparent images)
 * 5. Keep: p, br, span, a, img, table, tr, td, th, thead, tbody, ul, ol, li,
 *    h1-h6, blockquote, pre, code, em, strong, u, del, hr, div (with CSS isolation)
 */
function cleanupQuotedContent(html: string): string {
  try {
    const parser = new DOMParser()
    const pg = parser.parseFromString(html, 'text/html')

    // Remove unwanted top-level elements
    const evilTags = ['script', 'style', 'noscript', 'title', 'meta', 'base', 'head', 'link']
    for (const tag of evilTags) {
      for (const el of Array.from(pg.body.getElementsByTagName(tag))) {
        el.remove()
      }
    }
    // Remove external stylesheet links
    for (const el of Array.from(pg.body.querySelectorAll('link[rel="stylesheet"]'))) {
      el.remove()
    }

    // Remove all inline style attributes (prevent original bold/font-size leaks)
    for (const el of Array.from(pg.body.querySelectorAll('[style]'))) {
      el.removeAttribute('style')
    }

    // Remove tracking pixels (1x1 transparent images)
    for (const img of Array.from(pg.body.querySelectorAll('img'))) {
      const w = img.getAttribute('width')
      const h = img.getAttribute('height')
      if ((w === '1' || w === '0' || !w) && (h === '1' || h === '0' || !h)) {
        img.remove()
      }
    }

    // Get cleaned body HTML
    let cleaned = pg.body.innerHTML

    // Remove any stray HTML comment nodes
    cleaned = cleaned.replace(/<!--[\s\S]*?-->/g, '')

    // Remove leftover MSO/Outlook conditional tags
    cleaned = cleaned.replace(/<!--\[if[\s\S]*?\]>[\s\S]*?<!\[endif\]-->/gi, '')

    return cleaned
  } catch {
    return html
  }
}

// -------------------------------------------------------
// Subject auto-fill from document
// -------------------------------------------------------
function autoFillSubject() {
  const pg = propsRef.pg
  if (!pg) {
    form.subject = propsRef.referenceName || ''
    return
  }
  const subject = pg.subject_field || pg.title_field || pg.name || ''
  form.subject = subject
  if (propsRef.referenceName && !subject.includes(propsRef.referenceName)) {
    form.subject = `${subject} (#${propsRef.referenceName})`
  }
}

// -------------------------------------------------------
// Existing Document Attachments
// -------------------------------------------------------
const existingAttachments = ref<any[]>([])
const selectedExistingAttachments = ref<string[]>([])

async function loadExistingAttachments() {
  if (!propsRef.referencePagetype || !propsRef.referenceName) return
  try {
    const res = await api.call('jingrow.client.get_list', {
      pagetype: 'File',
      fields: ['name', 'file_name', 'file_url', 'is_private'],
      filters: JSON.stringify({
        attached_to_pagetype: propsRef.referencePagetype,
        attached_to_name: propsRef.referenceName,
      }),
      limit_page_length: 50,
    })
    const data = res?.message ?? res
    if (Array.isArray(data)) {
      existingAttachments.value = data.filter((f: any) => f.file_name)
    }
  } catch { /* ignore */ }
}

function toggleExistingAttachment(name: string) {
  const idx = selectedExistingAttachments.value.indexOf(name)
  if (idx >= 0) selectedExistingAttachments.value.splice(idx, 1)
  else selectedExistingAttachments.value.push(name)
}

// -------------------------------------------------------
// Draft auto-save (localStorage)
// -------------------------------------------------------
function getDraftKey(): string {
  const pt = propsRef.referencePagetype || 'Inbox'
  const nm = propsRef.referenceName || ''
  const key = propsRef.lastEmail?.name ? `:${propsRef.lastEmail.name}` : ''
  const subj = form.subject ? `:${form.subject}` : ''
  return `email_draft_${pt}_${nm}${key}${subj}`
}

function saveDraft() {
  const draft = {
    recipients: form.recipients,
    cc: form.cc,
    bcc: form.bcc,
    subject: form.subject,
    content: editorContent.value,
    sender: form.sender,
    emailTemplate: form.emailTemplate,
  }
  try {
    localStorage.setItem(getDraftKey(), JSON.stringify(draft))
  } catch { /* ignore */ }
}

async function restoreDraft() {
  try {
    const raw = localStorage.getItem(getDraftKey())
    if (!raw) return
    const draft = JSON.parse(raw)
    if (draft.recipients?.length) form.recipients = draft.recipients
    if (draft.cc?.length) form.cc = draft.cc
    if (draft.bcc?.length) form.bcc = draft.bcc
    if (draft.subject) form.subject = draft.subject
    if (draft.content) editorContent.value = draft.content
    if (draft.sender) form.sender = draft.sender
    if (draft.emailTemplate) form.emailTemplate = draft.emailTemplate
    localStorage.removeItem(getDraftKey()) // Remove after restore
  } catch { /* ignore */ }
}

function clearDraft() {
  try {
    localStorage.removeItem(getDraftKey())
  } catch { /* ignore */ }
}

// Auto-save draft every 3 seconds when visible
let draftTimer: ReturnType<typeof setInterval> | null = null
watch(visible, (v) => {
  if (v) {
    draftTimer = setInterval(saveDraft, 3000)
  } else {
    if (draftTimer) clearInterval(draftTimer)
    draftTimer = null
  }
})

// -------------------------------------------------------
// Attachments
// -------------------------------------------------------
const fileInputRef = ref<HTMLInputElement | null>(null)

function pickAttachments() {
  fileInputRef.value?.click()
}

function onFileSelected(e: Event) {
  const el = e.target as HTMLInputElement
  if (!el.files) return
  for (let i = 0; i < el.files.length; i++) {
    attachedFiles.value.push(el.files[i])
  }
  el.value = ''
}

function removeAttachment(idx: number) {
  attachedFiles.value.splice(idx, 1)
}

// -------------------------------------------------------
// Send email
// -------------------------------------------------------
const message = useMessage()

async function sendEmail() {
  if (!form.recipients.length) {
    message.warning(t('Enter Email Recipient(s)'))
    return
  }
  if (!form.subject.trim()) {
    message.warning(t('Subject is required'))
    return
  }

  sending.value = true
  try {
    // Upload attachments first
    const attachmentNames: string[] = []
    for (const file of attachedFiles.value) {
      try {
        const res = await uploadFileToTemp(file)
        if (res) attachmentNames.push(res)
      } catch (err) {
        console.error('[EmailCompose] Failed to upload attachment:', err)
      }
    }

    // Combine all attachments: uploaded + selected existing
    const allAttachments = [...attachmentNames, ...selectedExistingAttachments.value]

    const res = await api.call('jingrow.core.pagetype.email.email_helpers.make', {
      recipients: form.recipients.join(', '),
      cc: form.cc.join(', ') || undefined,
      bcc: form.bcc.join(', ') || undefined,
      subject: form.subject,
      content: editorContent.value,
      sender: form.sender || undefined,
      send_email: 1,
      send_me_a_copy: form.sendMeCopy ? 1 : 0,
      read_receipt: form.readReceipt ? 1 : 0,
      email_template: form.emailTemplate || undefined,
      attachments: allAttachments.length ? JSON.stringify(allAttachments) : undefined,
      pagetype: propsRef.referencePagetype || undefined,
      name: propsRef.referenceName || undefined,
      send_after: form.sendAfter ? new Date(form.sendAfter).toISOString() : undefined,
    })

    const result = res?.message ?? res
    message.success(t('Email Sent'))
    // Show unsubscribed notification if returned
    if (result?.emails_not_sent_to) {
      message.info(t('Email not sent to {0} (unsubscribed / disabled)', [result.emails_not_sent_to]))
    }
    clearDraft()
    emit('sent', result)
    close()
  } catch (err: any) {
    const errMsg = err?.message || t('Failed to send email')
    message.error(errMsg)
  } finally {
    sending.value = false
  }
}

/** Upload file to server and return the file name */
async function uploadFileToTemp(file: File): Promise<string | null> {
  const formData = new FormData()
  formData.append('file', file)
  formData.append('is_private', '1')
  formData.append('folder', 'Home/Attachments')
  try {
    const response = await fetch('/api/action/upload_file', {
      method: 'POST',
      body: formData,
      credentials: 'include',
    })
    const data = await response.json()
    return data?.message?.name || data?.message?.file_name || null
  } catch {
    return null
  }
}

function discard() {
  clearDraft()
  emit('discard')
  close()
}

// -------------------------------------------------------
// Save as Draft (server-side)
// -------------------------------------------------------
async function saveAsDraft() {
  savingDraft.value = true
  try {
    // Upload attachments first
    const attachmentNames: string[] = []
    for (const file of attachedFiles.value) {
      try {
        const res = await uploadFileToTemp(file)
        if (res) attachmentNames.push(res)
      } catch (err) {
        console.error('[EmailCompose] Failed to upload attachment:', err)
      }
    }
    const allAttachments = [...attachmentNames, ...selectedExistingAttachments.value]

    // Create Email record as Draft directly
    const res = await api.call('jingrow.core.pagetype.email.email_helpers.make', {
      recipients: form.recipients.join(', ') || undefined,
      cc: form.cc.join(', ') || undefined,
      bcc: form.bcc.join(', ') || undefined,
      subject: form.subject || t('No Subject'),
      content: editorContent.value,
      sender: form.sender || undefined,
      send_email: 0,
      send_me_a_copy: 0,
      read_receipt: 0,
      email_template: form.emailTemplate || undefined,
      attachments: allAttachments.length ? JSON.stringify(allAttachments) : undefined,
      pagetype: propsRef.referencePagetype || undefined,
      name: propsRef.referenceName || undefined,
      email_status: 'Draft',
    })

    clearDraft()
    message.success(t('Draft saved'))
    emit('sent', res?.message ?? res)
    visible.value = false
  } catch (err: any) {
    message.error(err?.message || t('Failed to save draft'))
  } finally {
    savingDraft.value = false
  }
}

// -------------------------------------------------------
// Helpers
// -------------------------------------------------------
function splitEmailList(str: string | undefined): string[] {
  if (!str) return []
  return str.split(/[;,]/).map(s => s.trim()).filter(Boolean)
}
</script>

<style scoped>
.email-compose {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.compose-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.field-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--n-text-color-3, #666);
  display: flex;
  align-items: center;
  gap: 8px;
}

.field-label .required {
  color: #d03050;
}

.toggle-cc-bcc {
  background: none;
  border: none;
  color: var(--n-primary-color, #18a058);
  cursor: pointer;
  font-size: 12px;
  padding: 0;
}

.toggle-cc-bcc:hover {
  text-decoration: underline;
}

.compose-body {
  flex: 1;
}

.message-editor-wrapper :deep(.jeditor-control .field-label) {
  display: none;
}

.message-editor-wrapper :deep(.jeditor-control .jeditor) {
  min-height: 220px;
}

.attachment-area {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.attached-file {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  background: var(--n-color-hover, #f5f5f5);
  border-radius: 4px;
  font-size: 12px;
}

.file-name {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.remove-file {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--n-text-color-3, #999);
  padding: 0;
  display: inline-flex;
}

.remove-file:hover {
  color: #d03050;
}

.add-attachment-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border: 1px dashed var(--n-border-color, #e0e0e6);
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  font-size: 12px;
  color: var(--n-primary-color, #18a058);
}

.add-attachment-btn:hover {
  background: var(--n-color-hover, #f5f5f5);
}

.compose-options {
  display: flex;
  gap: 20px;
  padding: 4px 0;
}

.compose-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Existing document attachments */
.existing-attach-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.existing-attach-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
}

.att-file-name {
  font-size: 12px;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.att-link {
  color: var(--n-primary-color, #18a058);
  display: inline-flex;
  align-items: center;
}

/* Schedule send - style override */
.compose-field :deep(.n-date-picker) {
  width: 100%;
}

/* LinkField - make input take full width */
.compose-field :deep(.link-field) {
  flex: 1;
}

.compose-field :deep(.link-input) {
  width: 100%;
}

.compose-field :deep(.link-field-container) {
  width: 100%;
}

/* Send button - brand style */
.send-btn-brand {
  background: #e6f8f0 !important;
  border: 1px solid #1fc76f !important;
  color: #0d684b !important;
}

.send-btn-brand :deep(.n-button__border) {
  border: none !important;
  border-color: transparent !important;
}

.send-btn-brand :deep(.n-button__state-border) {
  border: none !important;
  border-color: transparent !important;
}

.send-btn-brand:hover {
  background: #dcfce7 !important;
  border: 1px solid #1fc76f !important;
  color: #166534 !important;
  box-shadow: 0 2px 8px rgba(31, 199, 111, 0.15) !important;
}

/* Draft button - amber style */
.draft-btn {
  background: #fef3c7 !important;
  border: 1px solid #f59e0b !important;
  color: #92400e !important;
}

.draft-btn :deep(.n-button__border) {
  border: none !important;
  border-color: transparent !important;
}

.draft-btn :deep(.n-button__state-border) {
  border: none !important;
  border-color: transparent !important;
}

.draft-btn:hover {
  background: #fde68a !important;
  border: 1px solid #f59e0b !important;
  color: #78350f !important;
}

/* Email quote styles - quoted original message content
   Rendered as blockquote inside Tiptap editor */
.jeditor blockquote {
  border-left: 3px solid #d0d7de;
  background: #f8f9fa;
  padding: 8px 16px;
  margin: 8px 0;
  color: #57606a;
  font-size: 14px;
  border-radius: 0 4px 4px 0;
}

.jeditor blockquote p {
  margin: 0 0 6px 0;
  color: #57606a;
}

.jeditor blockquote p:last-child {
  margin-bottom: 0;
}

.jeditor blockquote img {
  max-width: 100%;
  height: auto;
  display: block;
  margin: 8px 0;
  border-radius: 4px;
}

.jeditor blockquote table {
  border-collapse: collapse;
  width: 100%;
  margin: 8px 0;
}

.jeditor blockquote table td,
.jeditor blockquote table th {
  border: 1px solid #e5e6eb;
  padding: 6px 10px;
}

.jeditor blockquote table th {
  background-color: #f0f2f5;
}

.jeditor blockquote pre {
  background: #f0f2f5;
  border-radius: 4px;
  padding: 8px 12px;
  overflow-x: auto;
  font-size: 13px;
}

/* Reserve top input space so user can reply above the quote */
.jeditor .cursor-space {
  min-height: 200px;
  margin: 0;
}

/* Separator line: -------Original message------- */
.jeditor :deep(.reply-original) {
  font-size: 11px;
  color: #57606a;
  margin: 4px 0;
  font-weight: 500;
}

/* Quote header - 4-line metadata with background */
.jeditor :deep(.quote-header) {
  background-color: #f5f5f5;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  padding: 5px 10px;
  margin-bottom: 10px;
  font-size: 12px;
  line-height: 1.6;
  color: #57606a;
}

.jeditor :deep(.quote-header p) {
  margin: 0;
  padding: 0;
  font-size: 12px;
}
</style>
<style>
/* Separator line: -------Original message------- */
.jeditor .reply-original {
  font-size: 11px;
  color: #57606a;
  margin: 4px 0;
  font-weight: 500;
}

/* Quote header - 4-line metadata with background */
.jeditor .quote-header {
  background-color: #f5f5f5;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  padding: 5px 10px;
  margin-bottom: 10px;
  font-size: 12px;
  line-height: 1.6;
  color: #57606a;
}

.jeditor .quote-header p {
  margin: 0;
  padding: 0;
  font-size: 12px;
}
</style>