<template>
  <div class="club-communication-page">
    <header class="page-header card">
      <div>
        <p class="page-eyebrow">TT-VEREIN</p>
        <h2>Kommunikation</h2>
        <p class="page-subtitle">
          Einzelnachrichten, Rundschreiben und Verteilergruppen in einem gemeinsamen Vereinskontext.
        </p>
      </div>
      <button type="button" class="btn-primary" :disabled="!canEdit" @click="resetThreadForm">
        Neuer Vorgang
      </button>
    </header>

    <div v-if="!canEdit && currentClub" class="state-banner">
      Lesemodus aktiv. Kommunikationsvorgänge können angezeigt, aber nicht bearbeitet werden.
    </div>

    <section v-if="!currentClub" class="card empty-state">
      <h3>Kein Verein ausgewählt</h3>
      <p>Bitte zuerst einen Verein auswählen, um Kommunikation zu verwalten.</p>
    </section>

    <template v-else>
      <section class="stats-grid">
        <article class="card stat-card">
          <span class="stat-label">Entwürfe</span>
          <strong class="stat-value">{{ draftThreads.length }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Gesendet</span>
          <strong class="stat-value">{{ sentThreads.length }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Verteilergruppen</span>
          <strong class="stat-value">{{ groups.length }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Mitglieder</span>
          <strong class="stat-value">{{ members.length }}</strong>
        </article>
        <article class="card stat-card">
          <span class="stat-label">Vorlagen</span>
          <strong class="stat-value">{{ templates.length }}</strong>
        </article>
      </section>

      <section class="communication-layout">
        <div class="communication-main">
          <section class="card filter-card">
            <div class="filter-grid">
              <label>
                <span>Status</span>
                <select v-model="filters.status">
                  <option value="">Alle</option>
                  <option value="draft">Entwurf</option>
                  <option value="scheduled">Geplant</option>
                  <option value="sent">Gesendet</option>
                  <option value="archived">Archiviert</option>
                </select>
              </label>
              <label>
                <span>Typ</span>
                <select v-model="filters.threadType">
                  <option value="">Alle</option>
                  <option value="direct">Einzelnachricht</option>
                  <option value="group">Gruppennachricht</option>
                  <option value="broadcast">Rundschreiben</option>
                </select>
              </label>
              <label class="search-field">
                <span>Suche</span>
                <input v-model.trim="filters.search" type="text" placeholder="Betreff, Empfänger oder Gruppe" />
              </label>
            </div>
          </section>

          <section class="card thread-list-card">
            <div class="section-header">
              <h3>Kommunikationsvorgänge</h3>
              <button type="button" class="btn-secondary" @click="loadCommunication" :disabled="loading">
                {{ loading ? 'Lädt…' : 'Neu laden' }}
              </button>
            </div>

            <p v-if="loadError" class="state-banner state-banner-error">{{ loadError }}</p>
            <p v-else-if="loading" class="state-banner">Kommunikation wird geladen…</p>
            <p v-else-if="filteredThreads.length === 0" class="state-banner">Keine Kommunikationsvorgänge im aktuellen Filter.</p>

            <div v-else class="thread-list">
              <div
                v-for="thread in filteredThreads"
                :key="thread.id"
                class="thread-row"
                :class="{ active: selectedThread?.id === thread.id }"
                @click="selectThread(thread)"
              >
                <div class="thread-row-main">
                  <div class="thread-row-topline">
                    <strong>{{ thread.subject }}</strong>
                    <div class="badge-row">
                      <span class="thread-badge" :class="`type-${thread.threadType}`">{{ displayThreadType(thread.threadType) }}</span>
                      <span class="thread-badge" :class="`status-${thread.status}`">{{ displayStatus(thread.status) }}</span>
                    </div>
                  </div>
                  <p class="thread-meta">
                    <span>{{ resolveThreadTarget(thread) }}</span>
                    <span>{{ formatDateTime(thread.sentAt || thread.scheduledAt || thread.updatedAt) }}</span>
                    <span>{{ thread.messages.length }} Nachrichten</span>
                    <span>{{ deliverySummary(thread) }}</span>
                  </p>
                  <p class="thread-preview">{{ previewMessageBody(thread.messages.at(-1)?.body || '') || 'Noch keine Nachricht erfasst.' }}</p>
                </div>
                <div class="thread-row-actions">
                  <button type="button" class="btn-secondary" :disabled="!canEdit || !canSendThread(thread)" @click.stop="sendThread(thread)">
                    {{ sendButtonLabel(thread) }}
                  </button>
                  <button type="button" class="btn-danger" :disabled="!canEdit" @click.stop="deleteThread(thread)">
                    Löschen
                  </button>
                </div>
              </div>
            </div>
          </section>

          <section class="card groups-card">
            <div class="section-header">
              <h3>Verteilergruppen</h3>
              <button type="button" class="btn-secondary" :disabled="!canEdit" @click="resetGroupForm">
                Neue Gruppe
              </button>
            </div>
            <p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Verteilergruppen bleiben sichtbar, Änderungen sind hier gesperrt.</p>

            <div class="groups-chip-list">
              <button
                v-for="group in groups"
                :key="group.id"
                type="button"
                class="group-chip"
                :class="{ active: selectedGroup?.id === group.id }"
                @click="selectGroup(group)"
              >
                {{ group.name }}
              </button>
            </div>

            <form class="group-form" @submit.prevent="saveGroup">
              <div class="form-grid">
                <label>
                  <span>Name</span>
                  <input v-model.trim="groupForm.name" type="text" :disabled="!canEdit" required />
                </label>
                <label>
                  <span>Typ</span>
                  <select v-model="groupForm.groupType" :disabled="!canEdit">
                    <option value="custom">Benutzerdefiniert</option>
                    <option value="manual">Manuell</option>
                    <option value="team">Team</option>
                    <option value="training_group">Trainingsgruppe</option>
                  </select>
                </label>
              </div>
              <label>
                <span>Beschreibung</span>
                <textarea v-model.trim="groupForm.description" rows="3" :disabled="!canEdit"></textarea>
              </label>
              <label>
                <span>Mitglieder</span>
                <select v-model="groupForm.memberIds" multiple size="8" :disabled="!canEdit">
                  <option v-for="member in members" :key="member.id" :value="member.id">
                    {{ member.lastName }}, {{ member.firstName }}
                  </option>
                </select>
              </label>
              <div class="filter-checkbox-grid">
                <label class="checkbox-row">
                  <input v-model="groupForm.filterDefinition.activeOnly" type="checkbox" :disabled="!canEdit" />
                  <span>Nur aktive Mitglieder</span>
                </label>
                <label class="checkbox-row">
                  <input v-model="groupForm.filterDefinition.onlyWithEmail" type="checkbox" :disabled="!canEdit" />
                  <span>Nur mit E-Mail-Adresse</span>
                </label>
                <label class="checkbox-row">
                  <input v-model="groupForm.filterDefinition.requiresSepaMandate" type="checkbox" :disabled="!canEdit" />
                  <span>Nur mit SEPA-Mandat</span>
                </label>
                <label class="checkbox-row">
                  <input v-model="groupForm.filterDefinition.missingSepaMandate" type="checkbox" :disabled="!canEdit" />
                  <span>Nur ohne SEPA-Mandat</span>
                </label>
              </div>
              <div class="form-actions">
                <button type="submit" class="btn-primary" :disabled="!canEdit || groupSaving">
                  {{ groupSaving ? 'Speichert…' : 'Gruppe speichern' }}
                </button>
                <button type="button" class="btn-secondary" @click="resetGroupForm">Zurücksetzen</button>
                <button type="button" class="btn-danger" :disabled="!canEdit || !groupForm.id" @click="deleteGroup">
                  Löschen
                </button>
              </div>
            </form>
          </section>
        </div>

        <aside class="communication-side">
          <section class="card thread-form-card">
            <div class="section-header">
              <h3>{{ threadForm.id ? 'Vorgang bearbeiten' : 'Neuer Vorgang' }}</h3>
            </div>
            <p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Vorgänge lassen sich prüfen, aber nicht ändern.</p>

            <form class="thread-form" @submit.prevent="saveThread">
              <div class="form-grid">
                <label>
                  <span>Typ</span>
                  <select v-model="threadForm.threadType" :disabled="!canEdit">
                    <option value="direct">Einzelnachricht</option>
                    <option value="group">Gruppennachricht</option>
                    <option value="broadcast">Rundschreiben</option>
                  </select>
                </label>
                <label>
                  <span>Status</span>
                  <select v-model="threadForm.status" :disabled="!canEdit">
                    <option value="draft">Entwurf</option>
                    <option value="scheduled">Geplant</option>
                    <option value="sent">Gesendet</option>
                    <option value="archived">Archiviert</option>
                  </select>
                </label>
              </div>

              <label>
                <span>Betreff</span>
                <input v-model.trim="threadForm.subject" type="text" :disabled="!canEdit" required />
              </label>

              <div v-if="threadForm.threadType === 'direct'">
                <label>
                  <span>Empfänger</span>
                  <select v-model="threadForm.recipientMemberId" :disabled="!canEdit">
                    <option value="">Bitte wählen</option>
                    <option v-for="member in members" :key="member.id" :value="member.id">
                      {{ member.lastName }}, {{ member.firstName }}
                    </option>
                  </select>
                </label>
              </div>

              <div v-if="threadForm.threadType === 'group'">
                <label>
                  <span>Verteilergruppe</span>
                  <select v-model="threadForm.distributionGroupId" :disabled="!canEdit">
                    <option value="">Bitte wählen</option>
                    <option v-for="group in groups" :key="group.id" :value="group.id">
                      {{ group.name }}
                    </option>
                  </select>
                </label>
              </div>

              <label>
                <span>Geplant für</span>
                <input v-model="threadForm.scheduledAt" type="datetime-local" :disabled="!canEdit" />
              </label>

              <div v-if="threadForm.threadType !== 'direct'" class="filter-checkbox-grid">
                <label class="checkbox-row">
                  <input v-model="threadForm.recipientFilters.activeOnly" type="checkbox" :disabled="!canEdit" />
                  <span>Nur aktive Mitglieder</span>
                </label>
                <label class="checkbox-row">
                  <input v-model="threadForm.recipientFilters.onlyWithEmail" type="checkbox" :disabled="!canEdit" />
                  <span>Nur mit E-Mail-Adresse</span>
                </label>
                <label class="checkbox-row">
                  <input v-model="threadForm.recipientFilters.requiresSepaMandate" type="checkbox" :disabled="!canEdit" />
                  <span>Nur mit SEPA-Mandat</span>
                </label>
                <label class="checkbox-row">
                  <input v-model="threadForm.recipientFilters.missingSepaMandate" type="checkbox" :disabled="!canEdit" />
                  <span>Nur ohne SEPA-Mandat</span>
                </label>
              </div>

              <div class="form-actions">
                <button type="submit" class="btn-primary" :disabled="!canEdit || saving">
                  {{ saving ? 'Speichert…' : 'Vorgang speichern' }}
                </button>
                <button type="button" class="btn-secondary" @click="resetThreadForm">Zurücksetzen</button>
              </div>
            </form>
          </section>

          <section class="card messages-card">
            <div class="section-header">
              <h3>Nachrichten</h3>
            </div>
            <p v-if="!canEdit && selectedThread" class="state-banner">Lesemodus aktiv. Verlauf und Versandstatus bleiben sichtbar, neue Einträge sind gesperrt.</p>

            <p v-if="!selectedThread" class="state-banner">Wähle links einen Kommunikationsvorgang aus.</p>
            <template v-else>
              <div class="recipient-panel">
                <h4>Empfänger</h4>
                <div v-if="selectedThread.recipients.length === 0" class="state-banner">
                  Noch keine Empfänger aufgelöst.
                </div>
                <div v-else class="recipient-list">
                  <div v-for="recipient in selectedThread.recipients" :key="recipient.id" class="recipient-row">
                    <div>
                      <strong>{{ recipient.recipientName }}</strong>
                      <div class="recipient-email">{{ recipient.emailSnapshot || 'Keine E-Mail-Adresse' }}</div>
                    </div>
                    <div class="recipient-status-block">
                      <span class="thread-badge" :class="`delivery-${recipient.deliveryStatus}`">{{ displayDeliveryStatus(recipient.deliveryStatus) }}</span>
                      <span v-if="recipient.retryable" class="recipient-retryable">Erneut versendbar</span>
                      <span v-if="recipient.deliveredAt" class="recipient-delivered-at">{{ formatDateTime(recipient.deliveredAt) }}</span>
                      <span v-else-if="recipient.lastAttemptAt" class="recipient-delivered-at">Letzter Versuch: {{ formatDateTime(recipient.lastAttemptAt) }}</span>
                      <span v-if="recipient.errorMessage" class="recipient-error">{{ recipient.errorMessage }}</span>
                    </div>
                  </div>
                </div>
              </div>

              <div class="recipient-panel">
                <h4>Versandprotokoll</h4>
                <div v-if="selectedThread.deliveryLogs.length === 0" class="state-banner">
                  Noch keine Versandversuche protokolliert.
                </div>
                <div v-else class="delivery-log-list">
                  <div v-for="logEntry in selectedThread.deliveryLogs" :key="logEntry.id" class="delivery-log-row">
                    <div>
                      <strong>{{ logEntry.recipientName }}</strong>
                      <div class="recipient-email">
                        Versuch {{ logEntry.attemptNo }} · {{ formatDateTime(logEntry.createdAt) }}
                      </div>
                    </div>
                    <div class="recipient-status-block">
                      <span class="thread-badge" :class="`delivery-${logEntry.status}`">{{ displayDeliveryStatus(logEntry.status) }}</span>
                      <span v-if="logEntry.retryable" class="recipient-retryable">Retry möglich</span>
                      <span v-if="logEntry.errorMessage" class="recipient-error">{{ logEntry.errorMessage }}</span>
                      <span v-else-if="logEntry.transportMessageId" class="recipient-delivered-at">{{ logEntry.transportMessageId }}</span>
                    </div>
                  </div>
                </div>
              </div>

              <div class="messages-list">
                <div v-if="selectedThread.messages.length === 0" class="state-banner">
                  Noch keine Nachrichten erfasst.
                </div>
                <div v-for="message in selectedThread.messages" :key="message.id" class="message-row">
                  <div class="message-row-topline">
                    <strong>{{ displayMessageLabel(message) }}</strong>
                    <span>{{ formatDateTime(message.createdAt) }}</span>
                  </div>
                  <div class="message-body" v-html="renderMessageBody(message.body)"></div>
                </div>
              </div>

              <form class="message-form" @submit.prevent="submitMessage">
                <label>
                  <span>Vorlage</span>
                  <select v-model="messageTemplateId" :disabled="!canEdit" @change="applyTemplate">
                    <option value="">Keine Vorlage</option>
                    <option v-for="template in templates" :key="template.id" :value="String(template.id)">
                      {{ template.name }}
                    </option>
                  </select>
                </label>
                <label>
                  <span>Neuer Eintrag</span>
                  <RichTextEditor v-model="messageForm.body" :disabled="!canEdit" placeholder="Nachricht oder interne Notiz" />
                </label>
                <div class="form-grid">
                  <label>
                    <span>Typ</span>
                    <select v-model="messageForm.messageType" :disabled="!canEdit">
                      <option value="message">Nachricht</option>
                      <option value="note">Interne Notiz</option>
                    </select>
                  </label>
                  <label>
                    <span>Richtung</span>
                    <select v-model="messageForm.direction" :disabled="!canEdit">
                      <option value="outbound">Ausgehend</option>
                      <option value="internal">Intern</option>
                      <option value="inbound">Eingehend</option>
                    </select>
                  </label>
                </div>
                <div class="form-actions">
                  <button type="submit" class="btn-primary" :disabled="!canEdit || messageSaving || !messageForm.body.trim()">
                    {{ messageSaving ? 'Speichert…' : 'Eintrag hinzufügen' }}
                  </button>
                  <button type="button" class="btn-secondary" :disabled="messageExporting || !messageForm.body.trim()" @click="exportWriting('message', 'pdf')">PDF</button>
                  <button type="button" class="btn-secondary" :disabled="messageExporting || !messageForm.body.trim()" @click="exportWriting('message', 'docx')">DOCX</button>
                  <button type="button" class="btn-secondary" :disabled="messageExporting || !messageForm.body.trim()" @click="exportWriting('message', 'odt')">ODT</button>
                </div>
              </form>
            </template>
          </section>

          <section class="card messages-card">
            <div class="section-header">
              <h3>Vorlagen & Antworten</h3>
            </div>
            <p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Vorlagen können eingesehen, aber nicht bearbeitet werden.</p>

            <div class="groups-chip-list">
              <button
                v-for="template in templates"
                :key="template.id"
                type="button"
                class="group-chip"
                :class="{ active: selectedTemplate?.id === template.id }"
                @click="selectTemplate(template)"
              >
                {{ template.name }}
              </button>
            </div>

            <form class="group-form" @submit.prevent="saveTemplate">
              <div class="form-grid">
                <label>
                  <span>Name</span>
                  <input v-model.trim="templateForm.name" type="text" :disabled="!canEdit" required />
                </label>
                <label>
                  <span>Kategorie</span>
                  <input v-model.trim="templateForm.category" type="text" :disabled="!canEdit" />
                </label>
              </div>
              <label>
                <span>Betreff-Vorlage</span>
                <input v-model.trim="templateForm.subjectTemplate" type="text" :disabled="!canEdit" />
              </label>
              <label>
                <span>Text-Vorlage</span>
                <RichTextEditor v-model="templateForm.bodyTemplate" :disabled="!canEdit" placeholder="Vorlageninhalt" />
              </label>
              <label>
                <span>Platzhalter / Antworten dokumentieren</span>
                <textarea v-model.trim="templateForm.variablesHint" rows="3" :disabled="!canEdit" placeholder="z. B. {{mitglied_name}}, {{verein_name}} oder Antwortvorgaben"></textarea>
              </label>
              <div class="form-actions">
                <button type="submit" class="btn-primary" :disabled="!canEdit || templateSaving">
                  {{ templateSaving ? 'Speichert…' : 'Vorlage speichern' }}
                </button>
                <button type="button" class="btn-secondary" @click="resetTemplateForm">Zurücksetzen</button>
                <button type="button" class="btn-danger" :disabled="!canEdit || !templateForm.id" @click="deleteTemplate">
                  Löschen
                </button>
                <button type="button" class="btn-secondary" :disabled="templateExporting || !templateForm.bodyTemplate.trim()" @click="exportWriting('template', 'pdf')">PDF</button>
                <button type="button" class="btn-secondary" :disabled="templateExporting || !templateForm.bodyTemplate.trim()" @click="exportWriting('template', 'docx')">DOCX</button>
                <button type="button" class="btn-secondary" :disabled="templateExporting || !templateForm.bodyTemplate.trim()" @click="exportWriting('template', 'odt')">ODT</button>
              </div>
            </form>
          </section>
        </aside>
      </section>
    </template>

    <InfoDialog
      v-model="infoDialog.isOpen"
      :title="infoDialog.title"
      :message="infoDialog.message"
      :details="infoDialog.details"
      :type="infoDialog.type"
    />

    <ConfirmDialog
      v-model="confirmDialog.isOpen"
      :title="confirmDialog.title"
      :message="confirmDialog.message"
      :details="confirmDialog.details"
      :type="confirmDialog.type"
      :confirm-text="confirmDialog.confirmText"
      :cancel-text="confirmDialog.cancelText"
      @confirm="handleConfirmResult(true)"
      @cancel="handleConfirmResult(false)"
    />
  </div>
</template>

<script>
import { mapGetters } from 'vuex';
import apiClient from '../apiClient.js';
import ConfirmDialog from '../components/ConfirmDialog.vue';
import InfoDialog from '../components/InfoDialog.vue';
import RichTextEditor from '../components/RichTextEditor.vue';
import { buildConfirmConfig, buildInfoConfig, safeErrorMessage } from '../utils/dialogUtils.js';
import {
  exportRichTextDocx,
  exportRichTextOdt,
  exportRichTextPdf,
  sanitizeRichTextHtml,
  stripRichTextToText,
} from '../utils/richTextDocumentExport.js';

function normalizeMember(member = {}) {
  return {
    id: Number(member.id),
    firstName: member.firstName || '',
    lastName: member.lastName || '',
  };
}

function normalizeGroup(group = {}) {
  return {
    id: Number(group.id),
    name: group.name || '',
    description: group.description || '',
    groupType: group.groupType || group.group_type || 'custom',
    filterDefinition: {
      activeOnly: group.filterDefinition?.activeOnly ?? group.filter_definition?.activeOnly ?? true,
      onlyWithEmail: Boolean(group.filterDefinition?.onlyWithEmail ?? group.filter_definition?.onlyWithEmail),
      missingEmail: Boolean(group.filterDefinition?.missingEmail ?? group.filter_definition?.missingEmail),
      requiresSepaMandate: Boolean(group.filterDefinition?.requiresSepaMandate ?? group.filter_definition?.requiresSepaMandate),
      missingSepaMandate: Boolean(group.filterDefinition?.missingSepaMandate ?? group.filter_definition?.missingSepaMandate),
      testMembersOnly: Boolean(group.filterDefinition?.testMembersOnly ?? group.filter_definition?.testMembersOnly),
    },
    memberships: Array.isArray(group.memberships) ? group.memberships.map((membership) => ({
      id: Number(membership.id),
      memberId: Number(membership.memberId || membership.member_id),
      member: membership.member ? normalizeMember(membership.member) : null,
    })) : [],
  };
}

function normalizeMessage(message = {}) {
  return {
    id: Number(message.id),
    body: message.body || '',
    messageType: message.messageType || message.message_type || 'message',
    direction: message.direction || 'outbound',
    createdAt: message.createdAt || message.created_at || '',
  };
}

function normalizeThread(thread = {}) {
  return {
    id: Number(thread.id),
    threadType: thread.threadType || thread.thread_type || 'direct',
    subject: thread.subject || '',
    status: thread.status || 'draft',
    recipientMemberId: Number(thread.recipientMemberId || thread.recipient_member_id || 0) || null,
    distributionGroupId: Number(thread.distributionGroupId || thread.distribution_group_id || 0) || null,
    scheduledAt: thread.scheduledAt || thread.scheduled_at || '',
    sentAt: thread.sentAt || thread.sent_at || '',
    updatedAt: thread.updatedAt || thread.updated_at || '',
    recipientFilters: {
      activeOnly: thread.recipientFilters?.activeOnly ?? thread.recipient_filters?.activeOnly ?? true,
      onlyWithEmail: Boolean(thread.recipientFilters?.onlyWithEmail ?? thread.recipient_filters?.onlyWithEmail),
      missingEmail: Boolean(thread.recipientFilters?.missingEmail ?? thread.recipient_filters?.missingEmail),
      requiresSepaMandate: Boolean(thread.recipientFilters?.requiresSepaMandate ?? thread.recipient_filters?.requiresSepaMandate),
      missingSepaMandate: Boolean(thread.recipientFilters?.missingSepaMandate ?? thread.recipient_filters?.missingSepaMandate),
      testMembersOnly: Boolean(thread.recipientFilters?.testMembersOnly ?? thread.recipient_filters?.testMembersOnly),
    },
    recipientMember: thread.recipientMember ? normalizeMember(thread.recipientMember) : null,
    distributionGroup: thread.distributionGroup ? normalizeGroup(thread.distributionGroup) : null,
    messages: Array.isArray(thread.messages) ? thread.messages.map(normalizeMessage) : [],
    recipients: Array.isArray(thread.recipients) ? thread.recipients.map((recipient) => ({
      id: Number(recipient.id),
      memberId: Number(recipient.memberId || recipient.member_id || 0) || null,
      recipientName: recipient.recipientName || recipient.recipient_name || '',
      emailSnapshot: recipient.emailSnapshot || recipient.email_snapshot || '',
      deliveryStatus: recipient.deliveryStatus || recipient.delivery_status || 'pending',
      deliveredAt: recipient.deliveredAt || recipient.delivered_at || '',
      lastAttemptAt: recipient.lastAttemptAt || recipient.last_attempt_at || '',
      attemptCount: Number(recipient.attemptCount || recipient.attempt_count || 0),
      retryable: Boolean(recipient.retryable),
      errorCode: recipient.errorCode || recipient.error_code || '',
      transportMessageId: recipient.transportMessageId || recipient.transport_message_id || '',
      errorMessage: recipient.errorMessage || recipient.error_message || '',
    })) : [],
    deliveryLogs: Array.isArray(thread.deliveryLogs) ? thread.deliveryLogs.map((logEntry) => ({
      id: Number(logEntry.id),
      recipientId: Number(logEntry.recipientId || logEntry.recipient_id || 0) || null,
      recipientName: logEntry.recipient?.recipientName || logEntry.recipient?.recipient_name || 'Unbekannter Empfänger',
      status: logEntry.status || 'failed',
      attemptNo: Number(logEntry.attemptNo || logEntry.attempt_no || 0),
      retryable: Boolean(logEntry.retryable),
      errorCode: logEntry.errorCode || logEntry.error_code || '',
      errorMessage: logEntry.errorMessage || logEntry.error_message || '',
      transportMessageId: logEntry.transportMessageId || logEntry.transport_message_id || '',
      createdAt: logEntry.createdAt || logEntry.created_at || '',
    })) : [],
  };
}

function normalizeTemplate(template = {}) {
  return {
    id: Number(template.id),
    name: template.name || '',
    category: template.category || 'general',
    subjectTemplate: template.subjectTemplate || template.subject_template || '',
    bodyTemplate: template.bodyTemplate || template.body_template || '',
    variablesHint: template.variablesHint || template.variables_hint || '',
  };
}

function createEmptyThreadForm() {
  return {
    id: null,
    threadType: 'direct',
    subject: '',
    status: 'draft',
    recipientMemberId: '',
    distributionGroupId: '',
    scheduledAt: '',
    recipientFilters: {
      activeOnly: true,
      onlyWithEmail: false,
      missingEmail: false,
      requiresSepaMandate: false,
      missingSepaMandate: false,
      testMembersOnly: false,
    },
  };
}

function createEmptyGroupForm() {
  return {
    id: null,
    name: '',
    description: '',
    groupType: 'custom',
    memberIds: [],
    filterDefinition: {
      activeOnly: true,
      onlyWithEmail: false,
      missingEmail: false,
      requiresSepaMandate: false,
      missingSepaMandate: false,
      testMembersOnly: false,
    },
  };
}

function createEmptyMessageForm() {
  return {
    body: '',
    messageType: 'message',
    direction: 'outbound',
  };
}

function createEmptyTemplateForm() {
  return {
    id: null,
    name: '',
    category: 'general',
    subjectTemplate: '',
    bodyTemplate: '',
    variablesHint: '',
  };
}

export default {
  name: 'ClubCommunicationView',
  components: {
    InfoDialog,
    ConfirmDialog,
    RichTextEditor,
  },
  data() {
    return {
      loading: false,
      saving: false,
      messageSaving: false,
      groupSaving: false,
      loadError: '',
      threads: [],
      groups: [],
      members: [],
      templates: [],
      selectedThreadId: null,
      selectedGroupId: null,
      selectedTemplateId: null,
      filters: {
        status: '',
        threadType: '',
        search: '',
      },
      threadForm: createEmptyThreadForm(),
      groupForm: createEmptyGroupForm(),
      messageForm: createEmptyMessageForm(),
      messageTemplateId: '',
      templateSaving: false,
      messageExporting: false,
      templateExporting: false,
      templateForm: createEmptyTemplateForm(),
      infoDialog: {
        isOpen: false,
        title: '',
        message: '',
        details: '',
        type: 'info',
      },
      confirmDialog: {
        isOpen: false,
        title: '',
        message: '',
        details: '',
        type: 'warning',
        confirmText: '',
        cancelText: '',
        resolveCallback: null,
      },
    };
  },
  computed: {
    ...mapGetters(['currentClub', 'hasPermission']),
    canEdit() {
      return this.hasPermission('communication', 'write');
    },
    selectedThread() {
      return this.threads.find((thread) => thread.id === this.selectedThreadId) || null;
    },
    selectedGroup() {
      return this.groups.find((group) => group.id === this.selectedGroupId) || null;
    },
    selectedTemplate() {
      return this.templates.find((template) => template.id === this.selectedTemplateId) || null;
    },
    filteredThreads() {
      const needle = this.filters.search.trim().toLowerCase();
      return this.threads.filter((thread) => {
        if (this.filters.status && thread.status !== this.filters.status) return false;
        if (this.filters.threadType && thread.threadType !== this.filters.threadType) return false;
        if (!needle) return true;
        return [
          thread.subject,
          thread.recipientMember ? `${thread.recipientMember.lastName} ${thread.recipientMember.firstName}` : '',
          thread.distributionGroup?.name || '',
          stripRichTextToText(thread.messages.at(-1)?.body || ''),
        ].join(' ').toLowerCase().includes(needle);
      });
    },
    draftThreads() {
      return this.threads.filter((thread) => thread.status === 'draft');
    },
    sentThreads() {
      return this.threads.filter((thread) => thread.status === 'sent');
    },
  },
  watch: {
    currentClub: {
      immediate: true,
      async handler(clubId) {
        if (!clubId) {
          this.clearCommunicationState();
          return;
        }
        await this.loadCommunication();
      },
    },
    selectedThread(thread) {
      if (!thread) {
        this.threadForm = createEmptyThreadForm();
        this.messageForm = createEmptyMessageForm();
        this.messageTemplateId = '';
        return;
      }
      this.threadForm = {
        id: thread.id,
        threadType: thread.threadType,
        subject: thread.subject,
        status: thread.status,
        recipientMemberId: thread.recipientMemberId || '',
        distributionGroupId: thread.distributionGroupId || '',
        scheduledAt: this.toDateTimeLocal(thread.scheduledAt),
        recipientFilters: { ...createEmptyThreadForm().recipientFilters, ...(thread.recipientFilters || {}) },
      };
      this.messageForm = createEmptyMessageForm();
      this.messageTemplateId = '';
    },
    selectedGroup(group) {
      if (!group) {
        this.groupForm = createEmptyGroupForm();
        return;
      }
      this.groupForm = {
        id: group.id,
        name: group.name,
        description: group.description,
        groupType: group.groupType,
        memberIds: group.memberships.map((membership) => membership.memberId),
        filterDefinition: { ...createEmptyGroupForm().filterDefinition, ...(group.filterDefinition || {}) },
      };
    },
    selectedTemplate(template) {
      if (!template) {
        this.templateForm = createEmptyTemplateForm();
        return;
      }
      this.templateForm = { ...template };
    },
  },
  methods: {
    clearCommunicationState() {
      this.threads = [];
      this.groups = [];
      this.members = [];
      this.templates = [];
      this.selectedThreadId = null;
      this.selectedGroupId = null;
      this.selectedTemplateId = null;
      this.threadForm = createEmptyThreadForm();
      this.groupForm = createEmptyGroupForm();
      this.templateForm = createEmptyTemplateForm();
      this.messageForm = createEmptyMessageForm();
      this.messageTemplateId = '';
      this.loadError = '';
    },
    showInfo(title, message, details = '', type = 'info') {
      this.infoDialog = buildInfoConfig({ title, message, details, type });
    },
    async showConfirm(title, message, details = '', type = 'warning', options = {}) {
      return new Promise((resolve) => {
        this.confirmDialog = buildConfirmConfig({
          title,
          message,
          details,
          type,
          resolveCallback: resolve,
          ...options,
        });
      });
    },
    handleConfirmResult(confirmed) {
      if (this.confirmDialog.resolveCallback) {
        this.confirmDialog.resolveCallback(confirmed);
        this.confirmDialog.resolveCallback = null;
      }
      this.confirmDialog.isOpen = false;
    },
    displayThreadType(type) {
      return {
        direct: 'Einzelnachricht',
        group: 'Gruppennachricht',
        broadcast: 'Rundschreiben',
      }[type] || type;
    },
    displayStatus(status) {
      return {
        draft: 'Entwurf',
        scheduled: 'Geplant',
        sent: 'Gesendet',
        archived: 'Archiviert',
      }[status] || status;
    },
    displayDeliveryStatus(status) {
      return {
        pending: 'Ausstehend',
        sent: 'Gesendet',
        failed: 'Fehlgeschlagen',
        skipped: 'Übersprungen',
      }[status] || status;
    },
    displayMessageLabel(message) {
      if (message?.direction === 'inbound') {
        return 'Antwort / Eingang';
      }
      if (message?.messageType === 'note') {
        return 'Interne Notiz';
      }
      if (message?.direction === 'internal') {
        return 'Interner Hinweis';
      }
      return 'Nachricht';
    },
    canSendThread(thread) {
      const recipients = Array.isArray(thread?.recipients) ? thread.recipients : [];
      return recipients.some((recipient) => {
        if (!recipient.emailSnapshot) return recipient.attemptCount === 0;
        if (recipient.deliveryStatus === 'pending') return true;
        return recipient.deliveryStatus === 'failed' && recipient.retryable;
      });
    },
    sendButtonLabel(thread) {
      return thread?.status === 'sent' ? 'Erneut senden' : 'Senden';
    },
    deliverySummary(thread) {
      const recipients = Array.isArray(thread?.recipients) ? thread.recipients : [];
      if (recipients.length === 0) {
        return '0 Empfänger';
      }
      const counts = recipients.reduce((acc, recipient) => {
        acc[recipient.deliveryStatus] = (acc[recipient.deliveryStatus] || 0) + 1;
        return acc;
      }, {});
      const retryableCount = recipients.filter((recipient) => recipient.retryable).length;
      return `${recipients.length} Empfänger · ${counts.sent || 0} gesendet · ${counts.pending || 0} offen · ${counts.failed || 0} Fehler${retryableCount ? ` · ${retryableCount} retrybar` : ''}`;
    },
    resolveThreadTarget(thread) {
      if (thread.threadType === 'direct') {
        return thread.recipientMember
          ? `${thread.recipientMember.lastName}, ${thread.recipientMember.firstName}`
          : 'Kein Empfänger';
      }
      if (thread.threadType === 'group') {
        return thread.distributionGroup?.name || 'Keine Verteilergruppe';
      }
      return 'Alle relevanten Empfänger';
    },
    formatDateTime(value) {
      if (!value) return 'Kein Datum';
      const date = new Date(value);
      if (Number.isNaN(date.getTime())) return 'Kein Datum';
      return new Intl.DateTimeFormat('de-DE', {
        dateStyle: 'medium',
        timeStyle: 'short',
      }).format(date);
    },
    toDateTimeLocal(value) {
      if (!value) return '';
      const date = new Date(value);
      if (Number.isNaN(date.getTime())) return '';
      const pad = (number) => String(number).padStart(2, '0');
      return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
    },
    async loadCommunication() {
      if (!this.currentClub) return;
      this.loading = true;
      this.loadError = '';
      try {
        const response = await apiClient.get(`/club-communication/${this.currentClub}`);
        this.threads = Array.isArray(response.data?.threads) ? response.data.threads.map(normalizeThread) : [];
        this.groups = Array.isArray(response.data?.groups) ? response.data.groups.map(normalizeGroup) : [];
        this.members = Array.isArray(response.data?.members) ? response.data.members.map(normalizeMember) : [];
        this.templates = Array.isArray(response.data?.templates) ? response.data.templates.map(normalizeTemplate) : [];
        if (this.selectedThreadId && !this.threads.some((thread) => thread.id === this.selectedThreadId)) {
          this.selectedThreadId = null;
        }
        if (this.selectedGroupId && !this.groups.some((group) => group.id === this.selectedGroupId)) {
          this.selectedGroupId = null;
        }
        if (this.selectedTemplateId && !this.templates.some((template) => template.id === this.selectedTemplateId)) {
          this.selectedTemplateId = null;
        }
        if (!this.selectedThreadId && this.threads.length > 0) {
          this.selectedThreadId = this.threads[0].id;
        } else if (this.threads.length === 0) {
          this.resetThreadForm();
        }
        if (this.groups.length === 0) {
          this.resetGroupForm();
        }
        if (this.templates.length === 0) {
          this.resetTemplateForm();
        }
      } catch (error) {
        this.loadError = safeErrorMessage(error, 'Kommunikation konnte nicht geladen werden.');
      } finally {
        this.loading = false;
      }
    },
    selectThread(thread) {
      this.selectedThreadId = thread.id;
    },
    selectGroup(group) {
      this.selectedGroupId = group.id;
    },
    selectTemplate(template) {
      this.selectedTemplateId = template.id;
    },
    resetThreadForm() {
      this.selectedThreadId = null;
      this.threadForm = createEmptyThreadForm();
      this.messageForm = createEmptyMessageForm();
      this.messageTemplateId = '';
    },
    resetGroupForm() {
      this.selectedGroupId = null;
      this.groupForm = createEmptyGroupForm();
    },
    resetTemplateForm() {
      this.selectedTemplateId = null;
      this.templateForm = createEmptyTemplateForm();
    },
    applyTemplate() {
      const template = this.templates.find((entry) => String(entry.id) === String(this.messageTemplateId));
      if (!template) {
        return;
      }
      if (template.subjectTemplate && !this.threadForm.subject.trim()) {
        this.threadForm.subject = template.subjectTemplate;
      }
      if (template.bodyTemplate) {
        this.messageForm.body = template.bodyTemplate;
      }
    },
    getWritingDraft(kind = 'message') {
      if (kind === 'template') {
        return {
          title: this.templateForm.name || 'Vorlage',
          subject: this.templateForm.subjectTemplate || '',
          bodyHtml: this.templateForm.bodyTemplate || '',
          baseName: this.templateForm.name || 'vorlage',
        };
      }
      return {
        title: this.threadForm.subject || 'Schreiben',
        subject: this.threadForm.subject || '',
        bodyHtml: this.messageForm.body || '',
        baseName: this.threadForm.subject || 'schreiben',
      };
    },
    buildExportFileName(baseName, extension) {
      const safeBase = String(baseName || 'schreiben')
        .trim()
        .toLowerCase()
        .replace(/[^a-z0-9äöüß._-]+/gi, '-')
        .replace(/-+/g, '-')
        .replace(/^-|-$/g, '');
      return `${safeBase || 'schreiben'}.${extension}`;
    },
    async exportWriting(kind, format) {
      const draft = this.getWritingDraft(kind);
      const text = stripRichTextToText(draft.bodyHtml);
      if (!text) {
        this.showInfo('Hinweis', 'Es gibt keinen Inhalt für den Export.', '', 'info');
        return;
      }

      const payload = {
        title: draft.title,
        subject: draft.subject,
        bodyHtml: sanitizeRichTextHtml(draft.bodyHtml),
      };

      try {
        if (kind === 'template') {
          this.templateExporting = true;
        } else {
          this.messageExporting = true;
        }
        if (format === 'pdf') {
          await exportRichTextPdf({ ...payload, filename: this.buildExportFileName(draft.baseName, 'pdf') });
        } else if (format === 'docx') {
          await exportRichTextDocx({ ...payload, filename: this.buildExportFileName(draft.baseName, 'docx') });
        } else if (format === 'odt') {
          await exportRichTextOdt({ ...payload, filename: this.buildExportFileName(draft.baseName, 'odt') });
        }
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Schreiben konnte nicht exportiert werden.'), '', 'error');
      } finally {
        this.messageExporting = false;
        this.templateExporting = false;
      }
    },
    previewMessageBody(body) {
      return stripRichTextToText(body || '');
    },
    renderMessageBody(body) {
      return sanitizeRichTextHtml(body || '');
    },
    async saveThread() {
      if (!this.currentClub || !this.canEdit) return;
      this.saving = true;
      try {
        const payload = {
          ...this.threadForm,
          recipientMemberId: this.threadForm.threadType === 'direct' ? this.threadForm.recipientMemberId || null : null,
          distributionGroupId: this.threadForm.threadType === 'group' ? this.threadForm.distributionGroupId || null : null,
          scheduledAt: this.threadForm.scheduledAt || null,
          recipientFilters: this.threadForm.threadType === 'direct' ? {} : this.threadForm.recipientFilters,
        };
        let savedThreadId = this.threadForm.id;
        if (this.threadForm.id) {
          const response = await apiClient.put(`/club-communication/${this.currentClub}/threads/${this.threadForm.id}`, payload);
          savedThreadId = response.data?.thread?.id || savedThreadId;
        } else {
          const response = await apiClient.post(`/club-communication/${this.currentClub}/threads`, payload);
          savedThreadId = response.data?.thread?.id || savedThreadId;
        }
        this.selectedThreadId = savedThreadId ? Number(savedThreadId) : null;
        await this.loadCommunication();
        this.showInfo('Erfolg', 'Kommunikationsvorgang gespeichert.', '', 'success');
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Kommunikationsvorgang konnte nicht gespeichert werden.'), '', 'error');
      } finally {
        this.saving = false;
      }
    },
    async sendThread(thread) {
      if (!this.currentClub || !this.canEdit || !thread?.id) return;
      try {
        await apiClient.patch(`/club-communication/${this.currentClub}/threads/${thread.id}/send`);
        await this.loadCommunication();
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Kommunikationsvorgang konnte nicht gesendet werden.'), '', 'error');
      }
    },
    async deleteThread(thread) {
      if (!this.currentClub || !this.canEdit || !thread?.id) return;
      const confirmed = await this.showConfirm(
        'Kommunikationsvorgang löschen',
        `Soll "${thread.subject}" gelöscht werden?`,
        '',
        'danger',
        { confirmText: 'Löschen', cancelText: 'Abbrechen' }
      );
      if (!confirmed) return;
      try {
        await apiClient.delete(`/club-communication/${this.currentClub}/threads/${thread.id}`);
        if (this.selectedThreadId === thread.id) {
          this.resetThreadForm();
        }
        await this.loadCommunication();
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Kommunikationsvorgang konnte nicht gelöscht werden.'), '', 'error');
      }
    },
    async submitMessage() {
      if (!this.currentClub || !this.canEdit || !this.selectedThread?.id) return;
      this.messageSaving = true;
      try {
        await apiClient.post(`/club-communication/${this.currentClub}/threads/${this.selectedThread.id}/messages`, this.messageForm);
        this.messageForm = createEmptyMessageForm();
        await this.loadCommunication();
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Nachricht konnte nicht gespeichert werden.'), '', 'error');
      } finally {
        this.messageSaving = false;
      }
    },
    async saveGroup() {
      if (!this.currentClub || !this.canEdit) return;
      this.groupSaving = true;
      try {
        const payload = {
          ...this.groupForm,
          filterDefinition: this.groupForm.filterDefinition,
        };
        let savedGroupId = this.groupForm.id;
        if (this.groupForm.id) {
          const response = await apiClient.put(`/club-communication/${this.currentClub}/groups/${this.groupForm.id}`, payload);
          savedGroupId = response.data?.group?.id || savedGroupId;
        } else {
          const response = await apiClient.post(`/club-communication/${this.currentClub}/groups`, payload);
          savedGroupId = response.data?.group?.id || savedGroupId;
        }
        this.selectedGroupId = savedGroupId ? Number(savedGroupId) : null;
        await this.loadCommunication();
        this.showInfo('Erfolg', 'Verteilergruppe gespeichert.', '', 'success');
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Verteilergruppe konnte nicht gespeichert werden.'), '', 'error');
      } finally {
        this.groupSaving = false;
      }
    },
    async deleteGroup() {
      if (!this.currentClub || !this.canEdit || !this.groupForm.id) return;
      const confirmed = await this.showConfirm(
        'Verteilergruppe löschen',
        `Soll "${this.groupForm.name}" gelöscht werden?`,
        'Verknüpfte Kommunikationsvorgänge müssen vorher umgestellt oder gelöscht werden.',
        'danger',
        { confirmText: 'Löschen', cancelText: 'Abbrechen' }
      );
      if (!confirmed) return;
      try {
        await apiClient.delete(`/club-communication/${this.currentClub}/groups/${this.groupForm.id}`);
        this.resetGroupForm();
        await this.loadCommunication();
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Verteilergruppe konnte nicht gelöscht werden.'), '', 'error');
      }
    },
    async saveTemplate() {
      if (!this.currentClub || !this.canEdit) return;
      this.templateSaving = true;
      try {
        let savedTemplateId = this.templateForm.id;
        if (this.templateForm.id) {
          const response = await apiClient.put(`/club-communication/${this.currentClub}/templates/${this.templateForm.id}`, this.templateForm);
          savedTemplateId = response.data?.template?.id || savedTemplateId;
        } else {
          const response = await apiClient.post(`/club-communication/${this.currentClub}/templates`, this.templateForm);
          savedTemplateId = response.data?.template?.id || savedTemplateId;
        }
        this.selectedTemplateId = savedTemplateId ? Number(savedTemplateId) : null;
        await this.loadCommunication();
        this.showInfo('Erfolg', 'Vorlage gespeichert.', '', 'success');
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Vorlage konnte nicht gespeichert werden.'), '', 'error');
      } finally {
        this.templateSaving = false;
      }
    },
    async deleteTemplate() {
      if (!this.currentClub || !this.canEdit || !this.templateForm.id) return;
      const confirmed = await this.showConfirm(
        'Vorlage löschen',
        `Soll "${this.templateForm.name}" gelöscht werden?`,
        '',
        'danger',
        { confirmText: 'Löschen', cancelText: 'Abbrechen' }
      );
      if (!confirmed) return;
      try {
        await apiClient.delete(`/club-communication/${this.currentClub}/templates/${this.templateForm.id}`);
        this.resetTemplateForm();
        await this.loadCommunication();
      } catch (error) {
        this.showInfo('Fehler', safeErrorMessage(error, 'Vorlage konnte nicht gelöscht werden.'), '', 'error');
      }
    },
  },
};
</script>

<style scoped>
.club-communication-page {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.page-header,
.empty-state,
.filter-card,
.thread-list-card,
.groups-card,
.thread-form-card,
.messages-card {
  padding: 1.25rem;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
}

.page-eyebrow {
  margin: 0 0 0.35rem;
  color: var(--text-light);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.8rem;
}

.page-subtitle {
  margin: 0.35rem 0 0;
  color: var(--text-secondary);
}

.stats-grid,
.filter-grid,
.form-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
}

.form-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.communication-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(320px, 0.95fr);
  gap: 1rem;
}

.communication-main,
.communication-side,
.thread-list,
.group-form,
.thread-form,
.messages-list,
.message-form {
  display: grid;
  gap: 1rem;
}

.search-field {
  grid-column: 1 / -1;
}

.filter-checkbox-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem 1rem;
}

.section-header,
.thread-row-topline,
.thread-row-actions,
.badge-row,
.form-actions,
.groups-chip-list,
.thread-row {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.section-header,
.thread-row-topline,
.thread-row {
  justify-content: space-between;
  align-items: center;
}

.thread-row {
  border: 1px solid rgba(24, 70, 54, 0.12);
  border-radius: 16px;
  padding: 1rem;
  cursor: pointer;
}

.thread-row.active {
  border-color: rgba(47, 122, 95, 0.55);
  background: rgba(47, 122, 95, 0.04);
}

.thread-row-main {
  display: grid;
  gap: 0.45rem;
}

.thread-meta,
.thread-preview {
  margin: 0;
  color: var(--text-secondary);
}

.thread-meta {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.thread-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  padding: 0.2rem 0.55rem;
  font-size: 0.78rem;
  font-weight: 700;
}

.type-direct {
  background: rgba(61, 118, 196, 0.12);
  color: #295b9c;
}

.type-group {
  background: rgba(160, 112, 64, 0.14);
  color: #8a5b1d;
}

.type-broadcast {
  background: rgba(47, 122, 95, 0.12);
  color: var(--primary-strong);
}

.status-draft {
  background: rgba(160, 112, 64, 0.14);
  color: #8a5b1d;
}

.status-scheduled {
  background: rgba(61, 118, 196, 0.12);
  color: #295b9c;
}

.status-sent {
  background: rgba(47, 122, 95, 0.12);
  color: var(--primary-strong);
}

.status-archived {
  background: #f2f4f7;
  color: #5f6b76;
}

.group-chip {
  border: 1px solid rgba(24, 70, 54, 0.14);
  background: rgba(255, 255, 255, 0.88);
  border-radius: 999px;
  padding: 0.45rem 0.75rem;
}

.group-chip.active {
  border-color: rgba(47, 122, 95, 0.5);
}

.message-row {
  border: 1px solid rgba(24, 70, 54, 0.1);
  border-radius: 12px;
  padding: 0.9rem 1rem;
}

.recipient-panel {
  display: grid;
  gap: 0.75rem;
}

.recipient-panel h4 {
  margin: 0;
}

.recipient-list {
  display: grid;
  gap: 0.6rem;
}

.recipient-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  border: 1px solid rgba(24, 70, 54, 0.08);
  border-radius: 12px;
  padding: 0.75rem 0.9rem;
}

.recipient-email,
.recipient-delivered-at {
  color: var(--text-secondary);
  font-size: 0.9rem;
}

.recipient-retryable {
  color: #9a2d7b;
  font-size: 0.85rem;
  font-weight: 600;
}

.recipient-status-block {
  display: grid;
  justify-items: end;
  gap: 0.35rem;
}

.delivery-log-list {
  display: grid;
  gap: 0.6rem;
}

.delivery-log-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  border: 1px solid rgba(24, 70, 54, 0.08);
  border-radius: 12px;
  padding: 0.75rem 0.9rem;
  background: rgba(255, 255, 255, 0.85);
}

.recipient-error {
  color: #8b1e1e;
  font-size: 0.9rem;
  text-align: right;
}

.message-row-topline {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  color: var(--text-secondary);
  margin-bottom: 0.5rem;
}

.message-row p {
  margin: 0;
  white-space: pre-wrap;
}

.message-body :deep(p) {
  margin: 0 0 0.6rem;
}

.message-body :deep(p:last-child) {
  margin-bottom: 0;
}

.message-body :deep(ul),
.message-body :deep(ol) {
  margin: 0.5rem 0 0.5rem 1.2rem;
  padding-left: 1rem;
}

.message-body :deep(a) {
  color: var(--primary-strong);
  text-decoration: underline;
}

.delivery-pending {
  background: rgba(160, 112, 64, 0.14);
  color: #8a5b1d;
}

.delivery-sent {
  background: rgba(47, 122, 95, 0.12);
  color: var(--primary-strong);
}

.delivery-failed,
.delivery-skipped {
  background: #fff1f0;
  color: #8b1e1e;
}

label {
  display: grid;
  gap: 0.4rem;
}

input,
select,
textarea {
  width: 100%;
}

.form-actions {
  justify-content: flex-start;
}

@media (max-width: 980px) {
  .communication-layout,
  .stats-grid,
  .filter-grid,
  .form-grid {
    grid-template-columns: 1fr;
  }
}
</style>
