<script setup lang="ts">
// Tier 2 Block F — host-facing communications surface. Compose, schedule,
// and send broadcasts; review what's already gone out; edit or cancel
// things that haven't fired yet (including the four auto-reminders the
// system seeds when an event is created).
//
// The compose form lives at the top of the card. Below it: tabs for
// Scheduled / Sent / Cancelled lists. We default to "Scheduled" because
// it's the one with actionable items most of the time.

interface Message {
  id: string
  send_at: string
  audience: 'all' | 'attending' | 'pending' | 'declined' | 'maybe'
  channel: 'email' | 'sms' | 'both'
  template_key?: string | null
  subject?: string | null
  body: string
  status: 'draft' | 'scheduled' | 'sending' | 'sent' | 'cancelled' | 'failed'
  sent_at?: string | null
  recipient_count?: number | null
  created_at: string
  delivery_stats?: { sent: number; failed: number; total: number }
}

const props = defineProps<{
  eventId: string
  yourRole?: 'owner' | 'editor' | 'viewer' | null
}>()

const canEdit = computed(() => props.yourRole === 'owner' || props.yourRole === 'editor')

const loading = ref(true)
const error = ref<string | null>(null)
const messages = ref<Message[]>([])

// Compose form state.
const audience = ref<Message['audience']>('pending')
const subject = ref('')
const body = ref('')
const sendMode = ref<'now' | 'schedule' | 'draft'>('now')
const sendAt = ref('') // datetime-local string
const sending = ref(false)
const recipientCount = ref<number | null>(null)
const countingRecipients = ref(false)

// Tab state for the message list.
const activeList = ref<'scheduled' | 'sent' | 'cancelled'>('scheduled')

// Toast.
type Toast = { kind: 'success' | 'error'; text: string }
const toast = ref<Toast | null>(null)
let toastTimer: ReturnType<typeof setTimeout> | null = null
function showToast(t: Toast, ms = 4000) {
  toast.value = t
  if (toastTimer) clearTimeout(toastTimer)
  toastTimer = setTimeout(() => { toast.value = null }, ms)
}

async function refresh() {
  loading.value = true
  try {
    const data = await useApi<{ messages: Message[] }>(`/events/${props.eventId}/messages`)
    messages.value = data.messages || []
  } catch (e: any) {
    error.value = useErrMessage(e, 'Could not load communications')
  } finally {
    loading.value = false
  }
}
onMounted(refresh)

// Live recipient count on audience change. Debounced via a single
// in-flight fetch so a rapid toggle doesn't fire a storm.
async function updateRecipientCount() {
  countingRecipients.value = true
  try {
    const res = await useApi<{ count: number }>(
      `/events/${props.eventId}/messages/recipient-count?audience=${audience.value}`,
    )
    recipientCount.value = res.count
  } catch {
    recipientCount.value = null
  } finally {
    countingRecipients.value = false
  }
}
watch(audience, updateRecipientCount, { immediate: true })

async function compose() {
  if (!body.value.trim()) {
    showToast({ kind: 'error', text: 'Body is required.' })
    return
  }
  sending.value = true
  try {
    const payload: Record<string, any> = {
      audience: audience.value,
      channel: 'email',
      subject: subject.value.trim() || undefined,
      body: body.value,
    }
    if (sendMode.value === 'draft') payload.draft = true
    if (sendMode.value === 'schedule' && sendAt.value) {
      // datetime-local has no timezone; treat as local + convert to ISO.
      payload.send_at = new Date(sendAt.value).toISOString()
    }
    // sendMode === 'now' falls through with no send_at; backend treats
    // that as "schedule immediately" (status=scheduled, send_at=now).

    await useApi(`/events/${props.eventId}/messages`, {
      method: 'POST',
      body: payload,
    })
    showToast({
      kind: 'success',
      text: sendMode.value === 'draft' ? 'Draft saved.'
          : sendMode.value === 'schedule' ? 'Message scheduled.'
          : 'Message queued to send.',
    })
    subject.value = ''
    body.value = ''
    sendAt.value = ''
    sendMode.value = 'now'
    await refresh()
  } catch (e: any) {
    showToast({ kind: 'error', text: useErrMessage(e, 'Could not compose message') })
  } finally {
    sending.value = false
  }
}

async function sendMessageNow(m: Message) {
  if (!confirm(`Send this message to ${m.audience} guests now?`)) return
  try {
    await useApi(`/events/${props.eventId}/messages/${m.id}/send-now`, { method: 'POST' })
    showToast({ kind: 'success', text: 'Message queued to send.' })
    await refresh()
  } catch (e: any) {
    showToast({ kind: 'error', text: useErrMessage(e, 'Could not send') })
  }
}

async function cancelMessage(m: Message) {
  const label = templateLabel(m) || 'this message'
  if (!confirm(`Cancel ${label}?`)) return
  try {
    await useApi(`/events/${props.eventId}/messages/${m.id}`, { method: 'DELETE' })
    showToast({ kind: 'success', text: 'Message cancelled.' })
    await refresh()
  } catch (e: any) {
    showToast({ kind: 'error', text: useErrMessage(e, 'Could not cancel') })
  }
}

// templateLabel maps the auto-seed keys to human strings so the UI
// reads "1-day reminder" rather than the internal slug.
function templateLabel(m: Message): string {
  switch (m.template_key) {
    case 'reminder_7d': return '7-day reminder'
    case 'last_call': return 'Last-call reminder'
    case 'reminder_1d': return '1-day reminder'
    case 'reminder_dayof': return 'Day-of reminder'
    case null:
    case undefined: return 'Custom broadcast'
    default: return m.template_key
  }
}

function audienceLabel(a: Message['audience']) {
  switch (a) {
    case 'all': return 'all guests'
    case 'attending': return 'attending guests'
    case 'pending': return 'guests who haven\'t replied'
    case 'declined': return 'guests who declined'
    case 'maybe': return 'guests who said maybe'
  }
}

function fmtDate(iso?: string | null) {
  if (!iso) return ''
  try { return new Date(iso).toLocaleString() } catch { return iso }
}

// Template-placeholder labels for the hint line under the compose
// textarea. Defined in the script so Vue's parser doesn't mistake the
// literal {{guest_name}} for a mustache expression.
const placeholderTokens = ['{{guest_name}}', '{{event_name}}', '{{event_date}}', '{{venue}}', '{{rsvp_link}}']

const scheduledMessages = computed(() =>
  messages.value.filter((m) => m.status === 'scheduled' || m.status === 'draft' || m.status === 'sending'))
const sentMessages = computed(() =>
  messages.value.filter((m) => m.status === 'sent'))
const cancelledMessages = computed(() =>
  messages.value.filter((m) => m.status === 'cancelled' || m.status === 'failed'))

const activeMessages = computed(() => {
  switch (activeList.value) {
    case 'scheduled': return scheduledMessages.value
    case 'sent': return sentMessages.value
    case 'cancelled': return cancelledMessages.value
  }
})
</script>

<template>
  <section class="card">
    <header class="mb-3">
      <h2 class="text-lg font-semibold">Communications</h2>
      <p class="text-xs text-zinc-500">
        Reminders and broadcasts to your guests. The big day's automatic nudges
        (7 days out, 3-day last call, 1 day before, and day-of) are pre-scheduled
        for you; edit or cancel anything you don't want.
      </p>
    </header>

    <p v-if="error" class="mb-3 text-sm text-red-400">{{ error }}</p>
    <p v-if="loading" class="text-sm text-zinc-500">Loading…</p>

    <div v-else class="space-y-6">
      <!-- Compose -->
      <div v-if="canEdit" class="rounded-lg border border-zinc-800 bg-zinc-950 p-4">
        <h3 class="mb-3 text-sm font-semibold text-zinc-100">Compose a message</h3>
        <div class="grid grid-cols-1 gap-3 md:grid-cols-2">
          <div>
            <label class="label">Audience</label>
            <select v-model="audience" class="input text-sm">
              <option value="all">Everyone</option>
              <option value="attending">Attending</option>
              <option value="pending">Haven't replied yet</option>
              <option value="declined">Declined</option>
              <option value="maybe">Maybe</option>
            </select>
            <p class="mt-1 text-xs text-zinc-500">
              <span v-if="countingRecipients">Counting…</span>
              <span v-else-if="recipientCount !== null">
                {{ recipientCount }} {{ recipientCount === 1 ? 'guest' : 'guests' }} will receive this.
              </span>
            </p>
          </div>

          <div>
            <label class="label">Subject (optional)</label>
            <input v-model="subject" class="input text-sm" placeholder="A friendly nudge from us" />
          </div>
        </div>

        <div class="mt-3">
          <label class="label">Message</label>
          <textarea
            v-model="body"
            class="input min-h-[100px] text-sm"
            placeholder="Hi {{guest_name}}, just a reminder about {{event_name}} on {{event_date}}. RSVP here: {{rsvp_link}}"
          ></textarea>
          <p class="mt-1 text-xs text-zinc-500">
            You can use these placeholders, and they'll be filled in per guest:
            <template v-for="(tok, i) in placeholderTokens" :key="tok">
              <code class="text-zinc-400">{{ tok }}</code><span v-if="i < placeholderTokens.length - 1">, </span>
            </template>.
          </p>
        </div>

        <div class="mt-3 grid grid-cols-1 gap-3 md:grid-cols-[1fr_auto]">
          <div>
            <label class="label">When</label>
            <div class="flex flex-wrap items-center gap-2">
              <label class="flex items-center gap-1.5 text-sm">
                <input v-model="sendMode" type="radio" value="now" />
                Send now
              </label>
              <label class="flex items-center gap-1.5 text-sm">
                <input v-model="sendMode" type="radio" value="schedule" />
                Schedule for…
              </label>
              <input
                v-if="sendMode === 'schedule'"
                v-model="sendAt"
                type="datetime-local"
                class="input text-sm"
              />
              <label class="flex items-center gap-1.5 text-sm">
                <input v-model="sendMode" type="radio" value="draft" />
                Save as draft
              </label>
            </div>
          </div>
          <div class="flex items-end">
            <button
              class="btn-primary text-sm"
              :disabled="sending || !body.trim() || (sendMode === 'schedule' && !sendAt)"
              @click="compose"
            >
              {{ sending ? 'Saving…' :
                  sendMode === 'now'       ? 'Send now' :
                  sendMode === 'schedule'  ? 'Schedule' :
                  'Save draft' }}
            </button>
          </div>
        </div>
      </div>

      <!-- List tabs -->
      <div>
        <div class="mb-3 flex items-center gap-1 rounded-lg border border-zinc-800 bg-zinc-900/40 p-1 text-sm">
          <button
            type="button"
            class="flex-1 rounded-md px-3 py-1.5 transition"
            :class="activeList === 'scheduled' ? 'bg-brand-500/10 text-brand-200' : 'text-zinc-400 hover:text-zinc-100'"
            @click="activeList = 'scheduled'"
          >Scheduled ({{ scheduledMessages.length }})</button>
          <button
            type="button"
            class="flex-1 rounded-md px-3 py-1.5 transition"
            :class="activeList === 'sent' ? 'bg-brand-500/10 text-brand-200' : 'text-zinc-400 hover:text-zinc-100'"
            @click="activeList = 'sent'"
          >Sent ({{ sentMessages.length }})</button>
          <button
            type="button"
            class="flex-1 rounded-md px-3 py-1.5 transition"
            :class="activeList === 'cancelled' ? 'bg-brand-500/10 text-brand-200' : 'text-zinc-400 hover:text-zinc-100'"
            @click="activeList = 'cancelled'"
          >Cancelled ({{ cancelledMessages.length }})</button>
        </div>

        <p v-if="!activeMessages.length" class="text-sm text-zinc-500">
          <template v-if="activeList === 'scheduled'">Nothing scheduled. New broadcasts and the auto-reminders will appear here.</template>
          <template v-else-if="activeList === 'sent'">Nothing has been sent yet.</template>
          <template v-else>No cancelled messages.</template>
        </p>

        <ul v-else class="space-y-2">
          <li
            v-for="m in activeMessages"
            :key="m.id"
            class="rounded-md border border-zinc-800 bg-zinc-950 p-3"
          >
            <div class="flex items-start justify-between gap-3">
              <div class="min-w-0 flex-1">
                <p class="text-sm font-medium text-zinc-100">
                  {{ templateLabel(m) }}
                  <span class="ml-1 text-xs font-normal text-zinc-500">
                    → {{ audienceLabel(m.audience) }}
                  </span>
                </p>
                <p v-if="m.subject" class="mt-0.5 truncate text-xs text-zinc-400">{{ m.subject }}</p>
                <p class="mt-1 text-xs text-zinc-500">
                  <template v-if="m.status === 'sent'">
                    Sent {{ fmtDate(m.sent_at) }}
                    <template v-if="m.delivery_stats">
                      · {{ m.delivery_stats.sent }} of {{ m.delivery_stats.total }} delivered
                      <span v-if="m.delivery_stats.failed > 0" class="text-amber-400">
                        ({{ m.delivery_stats.failed }} failed)
                      </span>
                    </template>
                  </template>
                  <template v-else-if="m.status === 'scheduled'">
                    Scheduled for {{ fmtDate(m.send_at) }}
                  </template>
                  <template v-else-if="m.status === 'sending'">
                    Sending now…
                  </template>
                  <template v-else-if="m.status === 'draft'">
                    Draft · saved {{ fmtDate(m.created_at) }}
                  </template>
                  <template v-else-if="m.status === 'cancelled'">
                    Cancelled
                  </template>
                  <template v-else-if="m.status === 'failed'">
                    <span class="text-red-400">Failed to send</span>
                  </template>
                </p>
                <p class="mt-2 line-clamp-2 text-xs text-zinc-400">{{ m.body }}</p>
              </div>
              <div v-if="canEdit && (m.status === 'scheduled' || m.status === 'draft')" class="flex shrink-0 items-center gap-2">
                <button
                  v-if="m.status === 'draft' || m.status === 'scheduled'"
                  type="button"
                  class="text-xs text-brand-300 hover:text-brand-200"
                  @click="sendMessageNow(m)"
                >Send now</button>
                <button
                  type="button"
                  class="text-xs text-zinc-400 hover:text-red-300"
                  @click="cancelMessage(m)"
                >Cancel</button>
              </div>
            </div>
          </li>
        </ul>
      </div>
    </div>

    <Teleport to="body">
      <Transition
        enter-active-class="transition duration-200 ease-out"
        enter-from-class="translate-y-2 opacity-0"
        enter-to-class="translate-y-0 opacity-100"
        leave-active-class="transition duration-200 ease-in"
        leave-from-class="translate-y-0 opacity-100"
        leave-to-class="translate-y-2 opacity-0"
      >
        <button
          v-if="toast"
          type="button"
          class="fixed bottom-6 right-6 z-50 flex max-w-sm items-center gap-2 rounded-lg border px-4 py-3 text-left text-sm shadow-lg backdrop-blur"
          :class="toast.kind === 'success'
            ? 'border-brand-700/60 bg-brand-950/90 text-brand-100'
            : 'border-red-800/60 bg-red-950/90 text-red-100'"
          role="status"
          @click="toast = null"
        >{{ toast.text }}</button>
      </Transition>
    </Teleport>
  </section>
</template>
