<template>
  <q-dialog :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)">
    <q-card style="width:560px;max-width:95vw" class="publish-modal">
      <q-card-section class="row items-center q-pb-sm" style="border-bottom:1px solid rgba(255,255,255,0.06)">
        <div class="col">
          <div class="text-subtitle1 text-weight-bold">Publier & envoyer l'horaire par SMS</div>
        </div>
        <q-btn flat round dense icon="close" color="grey-5" @click="$emit('update:modelValue', false)" />
      </q-card-section>

      <q-card-section class="q-gutter-md">
        <!-- Period -->
        <div>
          <div class="text-caption text-grey-5 q-mb-xs">Période</div>
          <div class="row items-center q-gutter-sm">
            <q-input v-model="startDate" type="date" dense outlined dark class="col" />
            <span class="text-grey-5">&rarr;</span>
            <q-input v-model="endDate" type="date" dense outlined dark class="col" />
          </div>
        </div>

        <!-- Employees -->
        <div>
          <div class="text-caption text-grey-5 q-mb-xs">Employés</div>
          <q-select v-model="selectedTechs" :options="techOptions" multiple use-chips
            dense outlined dark emit-value map-options
            option-value="value" option-label="label">
            <template v-slot:selected-item="{ opt, removeAtIndex, index }">
              <q-chip removable dense size="sm" color="indigo-8" text-color="white"
                @remove="removeAtIndex(index)">
                <q-avatar color="indigo-6" text-color="white" size="18px" class="q-mr-xs">T</q-avatar>
                {{ opt.label || opt }}
              </q-chip>
            </template>
          </q-select>
        </div>

        <!-- Draft count info -->
        <div v-if="draftCount > 0" class="text-caption" style="color:#a5b4fc">
          {{ draftCount }} travaux brouillon à publier pour cette période
        </div>
        <div v-else class="text-caption text-grey-6">
          Aucun brouillon à publier pour cette sélection
        </div>

        <!-- Include open jobs -->
        <q-checkbox v-model="includeOpen" label="Inclure les postes ouverts (non assignés)"
          dark dense color="indigo-6" />

        <!-- Additional message -->
        <div>
          <div class="text-caption text-grey-5 q-mb-xs">Message additionnel inclus dans le SMS envoyé aux employés</div>
          <q-input v-model="extraMessage" type="textarea" dense outlined dark
            placeholder="Message optionnel..." :input-style="{ minHeight: '48px' }" />
        </div>

        <!-- What the tech will receive -->
        <div class="sms-preview-hint">
          <q-icon name="info" size="xs" color="indigo-3" class="q-mr-xs" />
          <span>Chaque SMS contient l'horaire + deux liens&nbsp;:
            <b>📱&nbsp;Mes tâches</b> (application mobile) et
            <b>📅&nbsp;Ajouter à mon calendrier</b>
            (ajout automatique dans Google Agenda ou Apple Calendar — se met à jour tout seul).
          </span>
        </div>
      </q-card-section>

      <q-card-actions class="q-px-md q-pb-md">
        <q-btn unelevated label="Publier & Envoyer" color="red-7" icon="send"
          :loading="publishing" :disable="draftCount === 0 && !includeOpen"
          @click="onPublish" />
        <q-btn flat label="Ignorer" color="grey-5" @click="$emit('update:modelValue', false)" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { Notify } from 'quasar'
import { publishJobs } from 'src/api/dispatch'
import { sendTestSms } from 'src/api/sms'

const HUB_URL = window.location.hostname === 'localhost' ? 'http://localhost:3300' : 'https://msg.gigafibre.ca'

async function getMagicLink (techId) {
  try {
    const res = await fetch(`${HUB_URL}/magic-link/generate`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ tech_id: techId, ttl_hours: 72 }),
    })
    const data = await res.json()
    return data.ok ? data.link : null
  } catch { return null }
}

// Calendar subscription URL. webcal:// triggers native Calendar.app / Google
// Calendar "add subscription" flow on tap, so the tech's agenda auto-refreshes
// whenever dispatch updates jobs — no re-send required.
async function getIcalUrl (techId) {
  try {
    const res = await fetch(`${HUB_URL}/dispatch/ical-token/${encodeURIComponent(techId)}`)
    const data = await res.json()
    if (!data?.url) return null
    return HUB_URL.replace(/^https?:/, 'webcal:') + data.url
  } catch { return null }
}

const props = defineProps({
  modelValue: Boolean,
  jobs:        { type: Array, default: () => [] },
  technicians: { type: Array, default: () => [] },
  periodStart: { type: String, default: '' },
  periodEnd:   { type: String, default: '' },
})

const emit = defineEmits(['update:modelValue', 'published'])

const startDate = ref('')
const endDate = ref('')
const selectedTechs = ref([])
const includeOpen = ref(true)
const extraMessage = ref('')
const publishing = ref(false)

const techOptions = computed(() =>
  props.technicians
    .filter(t => t.active !== false)
    .map(t => ({ label: t.fullName || t.name, value: t.id }))
)

// Draft jobs matching period + selected techs
const draftJobs = computed(() => {
  const start = startDate.value
  const end = endDate.value
  const techIds = new Set(selectedTechs.value)
  return props.jobs.filter(j => {
    if (j.published) return false
    if (j.status === 'completed' || j.status === 'cancelled') return false
    if (!j.scheduledDate) return includeOpen.value
    if (start && j.scheduledDate < start) return false
    if (end && j.scheduledDate > end) return false
    if (techIds.size && j.assignedTech && !techIds.has(j.assignedTech)) return false
    if (!includeOpen.value && !j.assignedTech) return false
    return true
  })
})

const draftCount = computed(() => draftJobs.value.length)

// Reset on open
watch(() => props.modelValue, (open) => {
  if (open) {
    startDate.value = props.periodStart
    endDate.value = props.periodEnd
    selectedTechs.value = techOptions.value.map(t => t.value)
    includeOpen.value = true
    extraMessage.value = ''
  }
})

// ── Build SMS message per tech ──
function buildSmsForTech (tech, techJobs, magicLink = null, icalUrl = null) {
  const byDate = {}
  for (const j of techJobs) {
    const d = j.scheduledDate || 'Non planifié'
    if (!byDate[d]) byDate[d] = []
    byDate[d].push(j)
  }
  const dayNames = { 0: 'Dim', 1: 'Lun', 2: 'Mar', 3: 'Mer', 4: 'Jeu', 5: 'Ven', 6: 'Sam' }
  const lines = [`Horaire du ${fmtDate(startDate.value)} au ${fmtDate(endDate.value)}:`]
  const sortedDates = Object.keys(byDate).sort()
  for (const d of sortedDates) {
    const dt = new Date(d + 'T12:00:00')
    const dayLabel = isNaN(dt) ? d : `${dayNames[dt.getDay()]} ${dt.getDate()}`
    const jobDescs = byDate[d].map(j => {
      const time = j.startTime ? j.startTime.slice(0, 5) : ''
      const dur = j.duration ? `${j.duration}h` : ''
      const addr = j.address ? shortAddr(j.address) : ''
      return [time, j.subject, dur, addr].filter(Boolean).join(' - ')
    })
    lines.push(`${dayLabel}: ${jobDescs.join('; ')}`)
  }
  if (extraMessage.value.trim()) lines.push(extraMessage.value.trim())
  if (magicLink || icalUrl) lines.push('')
  if (magicLink) lines.push(`📱 Mes tâches: ${magicLink}`)
  if (icalUrl) lines.push(`📅 Ajouter à mon calendrier: ${icalUrl}`)
  return lines.join('\n')
}

function fmtDate (d) {
  if (!d) return '?'
  const dt = new Date(d + 'T12:00:00')
  return isNaN(dt) ? d : `${dt.getDate()}/${dt.getMonth() + 1}`
}

function shortAddr (addr) {
  if (!addr) return ''
  return addr.split(',')[0].trim().slice(0, 30)
}

async function onPublish () {
  publishing.value = true
  try {
    // 1. Collect job names to publish
    const jobNames = draftJobs.value.map(j => j.name || j.id)
    if (jobNames.length === 0) {
      Notify.create({ type: 'warning', message: 'Aucun brouillon à publier' })
      publishing.value = false
      return
    }

    // 2. Bulk publish via API
    const result = await publishJobs(jobNames)

    // 3. Send SMS to each selected tech (with magic link)
    const techIds = new Set(selectedTechs.value)
    let smsSent = 0
    let smsFailed = 0
    for (const tech of props.technicians) {
      if (!techIds.has(tech.id)) continue
      if (!tech.phone) continue
      const techJobs = draftJobs.value.filter(j => j.assignedTech === tech.id)
      if (!techJobs.length) continue
      const [magicLink, icalUrl] = await Promise.all([
        getMagicLink(tech.id),
        getIcalUrl(tech.id),
      ])
      const msg = buildSmsForTech(tech, techJobs, magicLink, icalUrl)
      try {
        await sendTestSms(tech.phone, msg, '', {
          reference_doctype: 'Dispatch Technician',
          reference_name: tech.name || tech.id,
        })
        smsSent++
      } catch (e) {
        console.warn(`SMS failed for ${tech.fullName}:`, e)
        smsFailed++
      }
    }

    // 4. Emit published event so parent updates store
    emit('published', jobNames)

    const parts = [`${result.published} travaux publiés`]
    if (smsSent) parts.push(`${smsSent} SMS envoyés`)
    if (smsFailed) parts.push(`${smsFailed} SMS échoués`)
    Notify.create({ type: 'positive', message: parts.join(', '), timeout: 4000 })
    emit('update:modelValue', false)
  } catch (err) {
    Notify.create({ type: 'negative', message: `Erreur: ${err.message}` })
  } finally {
    publishing.value = false
  }
}
</script>

<style scoped>
.publish-modal {
  background: #1a1e2e;
  color: #e2e4ef;
}
.sms-preview-hint {
  background: rgba(99, 102, 241, 0.08);
  border: 1px solid rgba(99, 102, 241, 0.25);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 11.5px;
  line-height: 1.45;
  color: #c7d2fe;
  display: flex;
  align-items: flex-start;
}
.sms-preview-hint b {
  color: #e0e7ff;
  font-weight: 600;
}
</style>
