<template>
  <q-page>
    <!-- Top bar: template selector + saved chip + quick actions. The Unlayer
         editor below has its own toolbar for blocks/preview/etc. -->
    <div class="row items-center q-px-md q-py-sm bg-white" style="border-bottom:1px solid #e5e7eb">
      <q-btn flat dense round icon="arrow_back" :to="'/campaigns'" class="q-mr-sm" />
      <div class="text-h6 q-mr-md">Éditeur de template</div>
      <q-select v-model="currentName" :options="templateOptions" emit-value map-options dense outlined
                style="min-width:240px" @update:model-value="onSelectTemplate" />
      <q-btn flat dense icon="add" label="Nouveau" color="primary" class="q-ml-sm" @click="newTemplateOpen = true">
        <q-tooltip>Créer un nouveau template (vide ou copié depuis un existant)</q-tooltip>
      </q-btn>
      <q-chip v-if="lastSavedTs" dense size="sm" color="grey-2" text-color="grey-9" class="q-ml-sm" icon="cloud_done">
        Sauvegardé · {{ lastSavedLabel }}
      </q-chip>
      <q-btn flat dense icon="data_object" label="Variables" color="grey-8"
             class="q-ml-sm" @click="variablesOpen = true">
        <q-tooltip>Voir toutes les variables Mustache disponibles et leur exemple</q-tooltip>
      </q-btn>
      <q-space />
      <q-btn flat color="primary" icon="visibility" label="Aperçu inbox" class="q-mr-sm" @click="openPreview">
        <q-tooltip>Voir le HTML rendu (substitué) tel que reçu par le destinataire</q-tooltip>
      </q-btn>
      <q-btn flat color="purple-7" icon="translate" label="Traduire (AI)" class="q-mr-sm"
             :disable="!aiTranslateTargetName" @click="aiTranslateOpen = true">
        <q-tooltip>{{ aiTranslateTargetName ? `Traduire vers ${aiTranslateTargetName} via Gemini` : 'Disponible pour les templates avec suffixe -fr ou -en' }}</q-tooltip>
      </q-btn>
      <q-btn flat color="warning" icon="send" label="Envoyer un test" class="q-mr-sm" @click="testSendOpen = true">
        <q-tooltip>Envoyer un courriel réel à une adresse de test</q-tooltip>
      </q-btn>
      <q-btn unelevated color="primary" icon="save" label="Enregistrer"
             :loading="saving" @click="saveTemplate" />
    </div>

    <!-- Unlayer editor — Vue 3 native, no iframe, full features:
         responsive preview, AMP blocks, Unsplash, file manager, dark mode,
         layers/structure panel, design tokens, etc.
         Wrapped in an explicit-sized container so the inner iframe gets
         enough height/width (Quasar's q-page doesn't propagate dimensions
         that easyEditor's nested iframe can pick up automatically). -->
    <div style="height: calc(100vh - 60px); width: 100%; overflow: hidden; position: relative;">
      <EmailEditor
        ref="editor"
        :options="editorOptions"
        :min-height="'100%'"
        style="height: 100%; width: 100%;"
        @load="onEditorLoad"
        @ready="onEditorReady"
      />
    </div>

    <!-- Aperçu dialog — renders the latest saved HTML with sample vars -->
    <q-dialog v-model="previewOpen" maximized persistent>
      <q-card class="bg-grey-2">
        <q-toolbar class="bg-white" style="border-bottom:1px solid #e5e7eb">
          <q-icon name="visibility" class="q-mr-sm" />
          <q-toolbar-title>Aperçu inbox · {{ currentName }}</q-toolbar-title>
          <q-btn flat dense round icon="close" @click="previewOpen = false" />
        </q-toolbar>
        <q-banner v-if="previewLoading" class="bg-blue-1 text-info"><q-spinner size="sm" /> Rendu en cours…</q-banner>
        <q-card-section style="height: calc(100vh - 60px); overflow:hidden">
          <iframe :srcdoc="previewHtmlContent" style="width:100%; height:100%; border:1px solid #e5e7eb; background:#fff;" />
        </q-card-section>
      </q-card>
    </q-dialog>

    <!-- New template dialog — name + starter -->
    <q-dialog v-model="newTemplateOpen" persistent>
      <q-card style="min-width: 500px; max-width: 90vw">
        <q-card-section class="row items-center bg-blue-1 text-info">
          <q-icon name="add" class="q-mr-sm" />
          <div class="text-h6">Nouveau template</div>
          <q-space />
          <q-btn flat dense round icon="close" v-close-popup />
        </q-card-section>
        <q-card-section>
          <q-input v-model="newTemplateForm.suffix" outlined dense autofocus
                   label="Nom (suffixe après gift-email-)" :prefix="newTemplateForm.prefix + '-'"
                   :rules="[v => /^[a-z0-9-]+$/.test(v) || 'Lettres minuscules, chiffres et tirets seulement']"
                   hint="Exemple: summer-2026, automne-promo, anniversaire" class="q-mb-md" />
          <q-select v-model="newTemplateForm.prefix" :options="['gift-email','newsletter','transactional']"
                    label="Type" outlined dense class="q-mb-md" />
          <q-select v-model="newTemplateForm.starter" :options="starterOptions" emit-value map-options
                    label="Démarrer depuis" outlined dense class="q-mb-md" />
          <q-banner v-if="newTemplateFinal" class="bg-grey-2 text-grey-8 q-mt-sm" rounded dense>
            <q-icon name="info" class="q-mr-xs" />
            Le template sera créé sous le nom <strong>{{ newTemplateFinal }}</strong>
            <span v-if="newTemplateForm.starter !== 'blank'">
              · contenu copié depuis <em>{{ newTemplateForm.starter }}</em>
            </span>
          </q-banner>
        </q-card-section>
        <q-card-actions align="right">
          <q-btn flat label="Annuler" v-close-popup />
          <q-btn unelevated color="primary" icon="add" label="Créer le template"
                 :loading="creating" :disable="!newTemplateValid" @click="createTemplate" />
        </q-card-actions>
      </q-card>
    </q-dialog>

    <!-- AI translate dialog -->
    <q-dialog v-model="aiTranslateOpen" persistent>
      <q-card style="min-width: 500px; max-width: 90vw">
        <q-card-section class="row items-center bg-purple-1 text-purple-9">
          <q-icon name="translate" class="q-mr-sm" />
          <div class="text-h6">Traduire avec Gemini AI</div>
          <q-space />
          <q-btn flat dense round icon="close" v-close-popup />
        </q-card-section>
        <q-card-section>
          <div class="q-mb-md">
            Le contenu de <strong>{{ currentName }}</strong> sera traduit vers
            <strong>{{ aiTranslateTargetName }}</strong> via Gemini Flash.
          </div>
          <q-banner class="bg-grey-2 text-grey-8 q-mb-md" rounded dense>
            <q-icon name="info" class="q-mr-xs" />
            <!-- v-pre on this span so Vue doesn't try to compile the literal
                 {{...}} braces inside the explanatory <code> tag. -->
            <span v-pre>
              Le AI préserve la structure HTML, les variables <code>{{...}}</code>,
              les URLs, les noms de marque (TARGO, Giftbit) et les emojis.
              Il traduit seulement le texte visible.
            </span>
          </q-banner>
          <q-banner v-if="targetTemplateExists" class="bg-amber-1 text-warning q-mb-md" rounded dense>
            <q-icon name="warning" class="q-mr-xs" />
            Le template <strong>{{ aiTranslateTargetName }}</strong> existe déjà.
            La traduction va l'écraser (backup automatique avant).
            <q-toggle v-model="aiTranslateOverride" label="Confirmer l'écrasement" class="q-mt-sm" />
          </q-banner>
        </q-card-section>
        <q-card-actions align="right">
          <q-btn flat label="Annuler" v-close-popup />
          <q-btn unelevated color="purple-7" icon="translate" label="Traduire maintenant"
                 :loading="aiTranslating"
                 :disable="targetTemplateExists && !aiTranslateOverride"
                 @click="doAiTranslate" />
        </q-card-actions>
      </q-card>
    </q-dialog>

    <!-- Test-send dialog -->
    <q-dialog v-model="testSendOpen" persistent>
      <q-card style="min-width: 500px; max-width: 90vw">
        <q-card-section class="row items-center bg-orange-1 text-warning">
          <q-icon name="send" class="q-mr-sm" />
          <div class="text-h6">Envoyer un test du courriel</div>
          <q-space />
          <q-btn flat dense round icon="close" v-close-popup />
        </q-card-section>
        <q-card-section>
          <q-input v-model="testSendForm.to" label="Adresse de destination" outlined dense type="email" autofocus class="q-mb-md" />
          <q-input v-model="testSendForm.subject" label="Sujet" outlined dense class="q-mb-md" />
          <div class="text-caption text-grey-7 q-mb-xs">Envoyer via</div>
          <q-btn-toggle v-model="testSendForm.via" spread no-caps unelevated toggle-color="primary" color="grey-3" text-color="grey-8" class="q-mb-md"
            :options="[{ label: 'Compte Gmail', value: 'gmail', icon: 'mail' }, { label: 'Mailjet', value: 'mailjet', icon: 'send' }]" />
          <div class="text-subtitle2 q-mb-sm">Variables</div>
          <div class="row q-col-gutter-sm">
            <q-input v-model="testSendForm.vars.firstname" label="firstname" outlined dense class="col-6" />
            <q-input v-model="testSendForm.vars.lastname" label="lastname" outlined dense class="col-6" />
            <q-input v-model="testSendForm.vars.amount" label="amount" outlined dense class="col-6" />
            <q-input v-model="testSendForm.vars.commitment_months" label="commitment_months" outlined dense class="col-6" />
            <q-input v-model="testSendForm.vars.gift_url" label="gift_url" outlined dense class="col-12" />
            <q-input v-model="testSendForm.vars.description" label="description" outlined dense class="col-12" />
            <q-input v-model="testSendForm.vars.expiry" label="expiry" outlined dense class="col-12" />
            <q-input v-model="testSendForm.vars.expires_at_date" label="expires_at_date (auto, date du wrapper)" outlined dense class="col-6" />
            <q-input v-model="testSendForm.vars.expires_in_days" label="expires_in_days" outlined dense class="col-6" />
          </div>
        </q-card-section>
        <q-card-section class="bg-grey-2">
          <div class="text-caption text-grey-8">
            Sauvegarde l'éditeur d'abord pour tester la dernière version.
            <template v-if="testSendForm.via === 'gmail'">Envoyé via le <b>compte Gmail</b> surveillé — même canal que les vraies invitations (étoiles d'évaluation cliquables incluses).</template>
            <template v-else>Envoyé via <b>Mailjet</b> depuis <code>TARGO &lt;support@targointernet.com&gt;</code>.</template>
          </div>
        </q-card-section>
        <q-card-actions align="right">
          <q-btn flat label="Annuler" v-close-popup />
          <q-btn unelevated color="primary" icon-right="send" label="Envoyer le test"
                 :loading="testSending" :disable="!testSendForm.to" @click="doTestSend" />
        </q-card-actions>
      </q-card>
    </q-dialog>

    <!-- Variables dialog — reference card showing every Mustache placeholder
         the worker recognises, with its sample value and a click-to-copy
         button so the user can paste it into any field that doesn't surface
         Unlayer's Merge Tags icon (e.g. the email subject in the campaign
         wizard, or a custom href). Source of truth is the same mergeTags
         array passed to Unlayer below — kept in sync via computed. -->
    <q-dialog v-model="variablesOpen">
      <q-card style="min-width: 540px; max-width: 720px">
        <q-card-section class="row items-center q-pb-none">
          <div class="text-h6"><q-icon name="data_object" class="q-mr-sm" />Variables disponibles</div>
          <q-space />
          <q-btn flat dense round icon="close" v-close-popup />
        </q-card-section>
        <q-card-section>
          <div class="text-caption text-grey-7 q-mb-md">
            Le worker du hub substitue ces variables dans le HTML au moment de l'envoi
            (moteur Mustache). Tu peux les insérer dans n'importe quel texte ou champ URL.
            Dans l'éditeur Unlayer, le moyen le plus rapide est : clique dans un texte →
            barre flottante → icône <code>{ }</code>.
          </div>
          <div v-for="cat in editorOptions.mergeTags" :key="cat.name" class="q-mb-md">
            <div class="text-subtitle2 text-grey-9 q-mb-xs">{{ cat.name }}</div>
            <q-list dense bordered class="rounded-borders">
              <q-item v-for="tag in cat.mergeTags" :key="tag.value" clickable
                      @click="copyVariable(tag.value)">
                <q-item-section avatar>
                  <code style="background:#F1F5F9;padding:2px 8px;border-radius:4px;font-size:13px">{{ tag.value }}</code>
                </q-item-section>
                <q-item-section>
                  <q-item-label>{{ tag.name }}</q-item-label>
                  <q-item-label caption>exemple : {{ tag.sample }}</q-item-label>
                </q-item-section>
                <q-item-section side>
                  <q-btn flat dense round icon="content_copy" size="sm" color="grey-7"
                         @click.stop="copyVariable(tag.value)">
                    <q-tooltip>Copier {{ tag.value }}</q-tooltip>
                  </q-btn>
                </q-item-section>
              </q-item>
            </q-list>
          </div>
          <q-banner class="bg-blue-1 text-info q-mt-md" rounded dense>
            <template v-slot:avatar><q-icon name="lightbulb" /></template>
            <span v-pre><strong>Bientôt :</strong> à l'importation CSV, on pourra mapper chaque colonne
            comme variable additionnelle (ex. <code>{{plan_name}}</code>,
            <code>{{renewal_date}}</code>) sans toucher au code.</span>
          </q-banner>
        </q-card-section>
      </q-card>
    </q-dialog>
  </q-page>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useQuasar } from 'quasar'
import { EmailEditor } from 'vue-email-editor'
import { listTemplates, getTemplate, saveTemplate as saveTemplateApi,
         previewTemplate, testSendTemplate, translateTemplate } from 'src/api/campaigns'
import { HUB_URL } from 'src/config/hub'

const route = useRoute()
const router = useRouter()
const $q = useQuasar()

// ── Editor ref + Unlayer configuration ──────────────────────────────────────
const editor = ref(null)
const editorReady = ref(false)
const saving = ref(false)
const currentName = ref(route.params.name || 'gift-email-fr')

// Unlayer editor options:
// - mergeTags: shown in the "Merge tags" panel, drag-droppable into text
// - features: Unsplash, file manager, etc. are all on by default
// - tools: which block types to expose
// - appearance: light theme matching our ops UI
const editorOptions = {
  appearance: {
    theme: 'modern_light',
    panels: {
      tools: { dock: 'left' },
    },
  },
  // Merge tags organized by category — Unlayer shows these in a dropdown
  // when editing a text block (click into text → toolbar → {} icon) and
  // ALSO in URL fields (Button "Action URL", Image "Source", mailto links).
  // The `sample` field is what Unlayer shows as a preview (so the user sees
  // realistic content while editing); on send, the hub's Mustache renderer
  // substitutes the actual value.
  mergeTags: [
    {
      name: 'Client',
      mergeTags: [
        { name: 'Prénom',          value: '{{firstname}}',   sample: 'Louis' },
        { name: 'Nom de famille',  value: '{{lastname}}',    sample: 'Tremblay' },
        { name: 'Courriel',        value: '{{email}}',       sample: 'exemple@gigafibre.ca' },
        { name: 'Adresse service', value: '{{description}}', sample: '123 Rue de la Rivière, Ste-Clotilde' },
      ],
    },
    {
      name: 'Offre',
      mergeTags: [
        { name: 'Montant',                    value: '{{amount}}',            sample: '60 $' },
        { name: 'Lien cadeau (URL)',          value: '{{gift_url}}',          sample: 'https://gft.link/abc' },
        { name: "Date d'expiration (texte)",  value: '{{expiry}}',            sample: '31 décembre 2026' },
        { name: 'Expiration auto (date)',     value: '{{expires_at_date}}',   sample: '21 août 2026' },
        { name: 'Expiration auto (jours)',    value: '{{expires_in_days}}',   sample: '90' },
        { name: 'Engagement (mois)',          value: '{{commitment_months}}', sample: '3' },
      ],
    },
    {
      name: 'Système',
      mergeTags: [
        { name: 'Année courante', value: '{{year}}', sample: '2026' },
      ],
    },
  ],
  // Display mode: 'email' (default, with mobile preview), 'web' for landing pages
  displayMode: 'email',
  // Locale for built-in strings
  locale: 'fr-CA',
  // Enable optional sidebar features (free tier limits some — see Unlayer docs)
  features: {
    // Built-in Unlayer template library — limited selection without projectId
    // but still gives the user some pre-built starts to pick from.
    templates: true,
    // Unsplash image search panel
    stockImages: true,
    // Image upload (uses Unlayer's CDN by default; can be wired to our hub
    // /campaigns/assets/upload endpoint via customJS later if we want to
    // self-host uploads — for now their CDN is fine for ad-hoc images)
    imageEditor: true,
    // Undo/redo + history
    undoRedo: true,
  },
  // Use Unlayer's free CDN. For paid users this would carry a projectId.
  // Without a projectId the "Powered by Unlayer" badge shows in the sidebar.
}

// ── Template list (selector at the top) ─────────────────────────────────────
const templates = ref([])
const templateOptions = computed(() => templates.value.map(t => ({
  label: `${t.name} (${Math.round(t.size / 1024)} KB)`,
  value: t.name,
})))

async function loadAvailableTemplates () {
  templates.value = await listTemplates()
}

// ── AI translation (Gemini via hub) ─────────────────────────────────────────
// Auto-detect source language from the template name suffix (-fr / -en) and
// compute the target name with the OPPOSITE suffix.
// Reference card showing every Mustache variable. Read-only — the variables
// list lives in editorOptions.mergeTags above (same source Unlayer uses).
const variablesOpen = ref(false)
async function copyVariable (val) {
  try {
    await navigator.clipboard.writeText(val)
    $q.notify({ type: 'positive', message: `${val} copié`, timeout: 1200 })
  } catch {
    $q.notify({ type: 'negative', message: 'Impossible de copier — sélectionne et copie manuellement' })
  }
}

const aiTranslateOpen = ref(false)
const aiTranslating = ref(false)
const aiTranslateOverride = ref(false)

const aiTranslateTargetName = computed(() => {
  const m = (currentName.value || '').match(/^(.+)-(fr|en)$/)
  if (!m) return ''
  const opposite = m[2] === 'fr' ? 'en' : 'fr'
  return `${m[1]}-${opposite}`
})

const targetTemplateExists = computed(() =>
  !!aiTranslateTargetName.value && !!templates.value.find(t => t.name === aiTranslateTargetName.value),
)

async function doAiTranslate () {
  if (!aiTranslateTargetName.value) return
  aiTranslating.value = true
  try {
    const r = await translateTemplate(currentName.value, aiTranslateTargetName.value, {
      override: aiTranslateOverride.value,
    })
    aiTranslateOpen.value = false
    aiTranslateOverride.value = false
    await loadAvailableTemplates()
    $q.notify({
      type: 'positive',
      message: `Traduction terminée : ${r.source} → ${r.target}`,
      caption: `${r.src_bytes} → ${r.out_bytes} octets (${r.from_lang} → ${r.to_lang})`,
      timeout: 6000,
      actions: [
        { label: 'Ouvrir', color: 'white', handler: () => { onSelectTemplate(r.target) } },
      ],
    })
  } catch (e) {
    $q.notify({ type: 'negative', message: 'Échec traduction: ' + e.message, timeout: 6000 })
  } finally {
    aiTranslating.value = false
  }
}

// ── New template creation ───────────────────────────────────────────────────
const newTemplateOpen = ref(false)
const creating = ref(false)
const newTemplateForm = ref({
  prefix: 'gift-email',
  suffix: '',
  starter: 'blank',   // 'blank' | template name to copy from
})

const newTemplateFinal = computed(() => {
  const { prefix, suffix } = newTemplateForm.value
  if (!suffix || !/^[a-z0-9-]+$/.test(suffix)) return ''
  return `${prefix}-${suffix}`
})

const newTemplateValid = computed(() =>
  !!newTemplateFinal.value &&
  !templates.value.find(t => t.name === newTemplateFinal.value),
)

const starterOptions = computed(() => [
  { label: 'Vide (canevas blanc)', value: 'blank' },
  ...templates.value.map(t => ({ label: `Copier depuis ${t.name}`, value: t.name })),
])

async function createTemplate () {
  if (!newTemplateValid.value) return
  creating.value = true
  try {
    const newName = newTemplateFinal.value
    let html = '<div style="padding:32px;text-align:center;color:#64748B;font-family:sans-serif;">Nouveau template — drag des blocs depuis la sidebar pour commencer.</div>'
    let design = null
    if (newTemplateForm.value.starter !== 'blank') {
      // Copy html + design from the chosen source template
      const src = await getTemplate(newTemplateForm.value.starter)
      html = src.html || html
      design = src.design || null
    }
    await saveTemplateApi(newName, html, { design })
    await loadAvailableTemplates()
    newTemplateOpen.value = false
    // Switch to the new template
    currentName.value = newName
    router.replace({ path: `/campaigns/templates/${newName}` })
    loadTemplateIntoEditor(newName)
    newTemplateForm.value.suffix = ''   // reset for next time
    $q.notify({ type: 'positive', message: `Template "${newName}" créé`, timeout: 3000 })
  } catch (e) {
    $q.notify({ type: 'negative', message: 'Erreur création: ' + e.message })
  } finally {
    creating.value = false
  }
}

// ── Load template into the Unlayer canvas on editor ready + on switch ──────
async function loadTemplateIntoEditor (name) {
  if (!editorReady.value || !editor.value) return
  try {
    const data = await getTemplate(name)
    // Priority: Unlayer design JSON saved by a previous edit > nothing.
    // Legacy MJML/HTML templates aren't auto-importable into Unlayer's
    // component tree — the user reconstructs visually once, and the
    // design saved by the next "Enregistrer" fixes future loads.
    if (data.design) {
      const design = typeof data.design === 'string' ? JSON.parse(data.design) : data.design
      editor.value.loadDesign(design)
    } else {
      // No saved design — vue-email-editor 2.x doesn't have a loadBlank()
      // method on the ref, so we just let the editor show its default
      // empty state ("No content here. Drag content from left.") and
      // notify the user to start building.
      $q.notify({
        type: 'info',
        message: `Pas encore de design pour "${name}" — drag des blocs depuis la sidebar gauche pour construire la template, puis "Enregistrer".`,
        timeout: 8000,
      })
    }
  } catch (e) {
    $q.notify({ type: 'negative', message: 'Erreur de chargement: ' + e.message })
  }
}

function onEditorLoad () {
  // Fired once when the editor IFRAME loads (before the editor inside is ready)
}

async function onEditorReady () {
  // Fired when the editor INSIDE the iframe is ready to accept loadDesign()
  editorReady.value = true
  // Images insérées → NOTRE store d'actifs auto-hébergé (pas le CDN d'Unlayer) ; les URLs des courriels pointent vers msg.gigafibre.ca.
  try {
    editor.value.registerCallback('image', (file, done) => {
      const f = file && file.attachments && file.attachments[0]
      if (!f) { done({ progress: 100 }); return }
      done({ progress: 20 })
      const fr = new FileReader()
      fr.onload = async () => {
        try {
          const r = await fetch(`${HUB_URL}/campaigns/assets/upload`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: f.name, data: fr.result }) })
          const d = await r.json()
          done({ progress: 100, url: d.url || '' })
        } catch (e) { done({ progress: 100 }) }
      }
      fr.onerror = () => done({ progress: 100 })
      fr.readAsDataURL(f)
    })
  } catch (e) { /* */ }
  await loadTemplateIntoEditor(currentName.value)
}

function onSelectTemplate (name) {
  currentName.value = name
  router.replace({ path: `/campaigns/templates/${name}` })
  loadTemplateIntoEditor(name)
}

// ── Save: export HTML + design JSON, POST to hub ────────────────────────────
const lastSavedTs = ref(null)
const lastSavedLabel = computed(() => {
  if (!lastSavedTs.value) return ''
  const diff = Math.floor((Date.now() - lastSavedTs.value) / 1000)
  if (diff < 60) return `il y a ${diff}s`
  if (diff < 3600) return `il y a ${Math.floor(diff / 60)}min`
  return new Date(lastSavedTs.value).toLocaleTimeString('fr-CA')
})

function saveTemplate () {
  if (!editor.value) return
  saving.value = true
  // exportHtml uses a callback (legacy Unlayer API) — wrap in a Promise
  editor.value.exportHtml(async (data) => {
    try {
      const { html, design } = data
      await saveTemplateApi(currentName.value, html, { design })
      lastSavedTs.value = Date.now()
      $q.notify({ type: 'positive', message: 'Template enregistré ✓', timeout: 2500 })
    } catch (e) {
      $q.notify({ type: 'negative', message: 'Erreur: ' + e.message })
    } finally {
      saving.value = false
    }
  })
}

// ── Preview dialog ──────────────────────────────────────────────────────────
const previewOpen = ref(false)
const previewLoading = ref(false)
const previewHtmlContent = ref('')

async function openPreview () {
  previewOpen.value = true
  previewLoading.value = true
  try {
    const r = await previewTemplate(currentName.value)
    previewHtmlContent.value = r.rendered || ''
  } catch (e) {
    $q.notify({ type: 'negative', message: 'Aperçu impossible: ' + e.message })
  } finally {
    previewLoading.value = false
  }
}

// ── Test-send dialog ────────────────────────────────────────────────────────
const testSendOpen = ref(false)
const testSending = ref(false)
// Sample expiry — 30 days from now, locale-formatted FR. The Mustache
// section {{#expires_at_date}}…{{/expires_at_date}} guards visible
// blocks, so leaving this blank would hide them in tests. We compute
// a realistic value so test sends and previews show the real layout.
const sampleExpiryDate = new Date(Date.now() + 30 * 86400 * 1000)
  .toLocaleDateString('fr-CA', { day: 'numeric', month: 'long', year: 'numeric' })

const testSendForm = ref({
  to: '',
  subject: '[TEST] Aperçu du courriel TARGO',
  via: 'gmail',
  vars: {
    firstname: 'Louis', lastname: 'Test', amount: '60 $',
    commitment_months: '3',
    gift_url: 'https://gft.link/TEST123',
    description: '123 Rue de Test, Ste-Clotilde',
    expiry: '31 décembre 2026',
    expires_at_date: sampleExpiryDate,
    expires_in_days: '30',
  },
})

async function doTestSend () {
  testSending.value = true
  try {
    const r = await testSendTemplate(currentName.value, {
      to: testSendForm.value.to.trim(),
      subject: testSendForm.value.subject,
      vars: testSendForm.value.vars,
      via: testSendForm.value.via,
    })
    $q.notify({ type: 'positive', message: `Test envoyé à ${r.to}`, caption: `via ${r.channel === 'gmail' ? 'Gmail' : 'Mailjet'} · ${r.bytes} octets`, timeout: 5000 })
    testSendOpen.value = false
  } catch (e) {
    $q.notify({ type: 'negative', message: 'Échec envoi: ' + e.message })
  } finally {
    testSending.value = false
  }
}

onMounted(loadAvailableTemplates)
</script>
