<script setup lang="ts">
import type { MailMessageDetailDto, MailAddressDto, MailAttachmentDto } from '~/modules/mail/services/dto/mail'
import { sanitizeMailHtml } from '~/utils/sanitizeMailHtml'
import { useMailService } from '~/modules/mail/services/mail'

const props = defineProps<{
    /** Détail complet du message. null = aucun message sélectionné. */
    detail: MailMessageDetailDto | null
    loading: boolean
}>()

const emit = defineEmits<{
    createTask: [mailId: number]
    linkTask: [mailId: number]
}>()

const { t } = useI18n()
const mailService = useMailService()

const showImages = ref(false)

const sanitizedBody = computed((): string => {
    if (!props.detail?.bodyHtml) return ''
    return sanitizeMailHtml(props.detail.bodyHtml, { allowImages: showImages.value })
})

// ─── Pièces jointes : aperçu / téléchargement ──────────────────────────────

function isImage(mime: string): boolean {
    return mime.startsWith('image/')
}

function isPdf(mime: string): boolean {
    return mime === 'application/pdf'
}

function isPreviewable(mime: string): boolean {
    return isImage(mime) || isPdf(mime)
}

function attachmentIcon(mime: string): string {
    if (isImage(mime)) return 'material-symbols:image-outline'
    if (isPdf(mime)) return 'material-symbols:picture-as-pdf-outline'
    return 'material-symbols:attach-file'
}

const previewOpen = ref(false)
const previewLoading = ref(false)
const previewAtt = ref<MailAttachmentDto | null>(null)
const previewUrl = ref<string | null>(null)
let previewBlob: Blob | null = null

function revokePreview(): void {
    if (previewUrl.value) {
        URL.revokeObjectURL(previewUrl.value)
        previewUrl.value = null
    }
    previewBlob = null
}

watch(
    () => props.detail?.header.id,
    () => {
        showImages.value = false
        previewOpen.value = false
        revokePreview()
    },
)

watch(previewOpen, (open) => {
    if (!open) revokePreview()
})

onBeforeUnmount(revokePreview)

async function handleAttachmentClick(att: MailAttachmentDto): Promise<void> {
    if (!isPreviewable(att.mimeType)) {
        await handleDownload(att.downloadId, att.filename)
        return
    }

    previewAtt.value = att
    previewUrl.value = null
    previewLoading.value = true
    previewOpen.value = true

    try {
        const { data } = await mailService.downloadAttachment(att.downloadId)
        previewBlob = data
        previewUrl.value = URL.createObjectURL(data)
    } catch {
        // useApi affiche déjà le toast — on referme la visionneuse.
        previewOpen.value = false
    } finally {
        previewLoading.value = false
    }
}

function downloadFromPreview(): void {
    const att = previewAtt.value
    if (!att) return
    if (previewBlob) {
        triggerBlobDownload(previewBlob, att.filename)
    } else {
        void handleDownload(att.downloadId, att.filename)
    }
}

function triggerBlobDownload(blob: Blob, filename: string): void {
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = filename
    a.click()
    URL.revokeObjectURL(url)
}

async function handleDownload(downloadId: string, filename: string): Promise<void> {
    try {
        const { data } = await mailService.downloadAttachment(downloadId)
        triggerBlobDownload(data, filename)
    } catch {
        // L'erreur est gérée par useApi (toast automatique)
    }
}

function formatDate(iso: string | null): string {
    if (!iso) return ''
    return new Date(iso).toLocaleString('fr', {
        dateStyle: 'long',
        timeStyle: 'short',
    })
}

function joinAddresses(addresses: MailAddressDto[]): string {
    return addresses
        .map((a) => (a.name ? `${a.name} <${a.email}>` : a.email))
        .join(', ')
}
</script>

<template>
    <div class="flex h-full flex-col overflow-hidden">
        <div
            v-if="!detail && !loading"
            class="flex flex-1 items-center justify-center text-sm text-neutral-400 italic px-8 text-center"
        >
            {{ t('mail.empty.viewer') }}
        </div>

        <div v-else-if="loading" class="flex flex-1 items-center justify-center">
            <Icon name="material-symbols:progress-activity" size="28" class="animate-spin text-neutral-400" />
        </div>

        <template v-else-if="detail">
            <div class="flex-shrink-0 border-b border-neutral-200 px-4 py-3 space-y-1.5">
                <h2 class="text-base font-semibold text-neutral-900 break-words">
                    {{ detail.header.subject ?? t('mail.noSubject') }}
                </h2>

                <dl class="text-xs text-neutral-500 space-y-0.5">
                    <div class="flex gap-1.5">
                        <dt class="font-medium text-neutral-600 w-5 flex-shrink-0">{{ t('mail.from') }}</dt>
                        <dd class="break-all">
                            {{
                                detail.header.fromName
                                    ? `${detail.header.fromName} <${detail.header.fromEmail}>`
                                    : (detail.header.fromEmail ?? '')
                            }}
                        </dd>
                    </div>
                    <div v-if="detail.header.toRecipients.length > 0" class="flex gap-1.5">
                        <dt class="font-medium text-neutral-600 w-5 flex-shrink-0">{{ t('mail.to') }}</dt>
                        <dd class="break-all">{{ joinAddresses(detail.header.toRecipients) }}</dd>
                    </div>
                    <div v-if="detail.header.ccRecipients.length > 0" class="flex gap-1.5">
                        <dt class="font-medium text-neutral-600 w-5 flex-shrink-0">{{ t('mail.cc') }}</dt>
                        <dd class="break-all">{{ joinAddresses(detail.header.ccRecipients) }}</dd>
                    </div>
                    <div class="flex gap-1.5">
                        <dt class="font-medium text-neutral-600 w-5 flex-shrink-0">{{ t('mail.date') }}</dt>
                        <dd>{{ formatDate(detail.header.sentAt ?? detail.header.receivedAt) }}</dd>
                    </div>
                </dl>

                <div class="flex flex-wrap items-center gap-2 pt-1">
                    <MalioButton
                        :label="t('mail.actions.createTask')"
                        variant="primary"
                        icon-name="material-symbols:add-task-outline"
                        icon-position="left"
                        :icon-size="13"
                        button-class="text-xs px-2.5 py-1"
                        @click="emit('createTask', detail.header.id)"
                    />
                    <MalioButton
                        :label="t('mail.actions.linkTask')"
                        variant="secondary"
                        icon-name="material-symbols:link"
                        icon-position="left"
                        :icon-size="13"
                        button-class="text-xs px-2.5 py-1"
                        @click="emit('linkTask', detail.header.id)"
                    />
                </div>
            </div>

            <div class="flex-1 overflow-y-auto px-4 py-3">
                <div
                    v-if="!showImages && detail.bodyHtml"
                    class="mb-3 flex items-center gap-3 rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-sm"
                >
                    <Icon name="material-symbols:image-outline" size="16" class="text-amber-500 flex-shrink-0" />
                    <span class="flex-1 text-amber-700">
                        {{ t('mail.remoteImagesBlocked') }}
                    </span>
                    <button
                        type="button"
                        class="text-xs font-medium text-amber-700 underline hover:text-amber-900 transition-colors"
                        @click="showImages = true"
                    >
                        {{ t('mail.actions.showImages') }}
                    </button>
                </div>

                <div
                    v-if="detail.bodyHtml"
                    class="prose prose-sm max-w-none text-neutral-800"
                    v-html="sanitizedBody"
                />

                <pre
                    v-else-if="detail.bodyText"
                    class="whitespace-pre-wrap font-sans text-sm text-neutral-700"
                >{{ detail.bodyText }}</pre>
            </div>

            <div
                v-if="detail.attachments.length > 0"
                class="flex-shrink-0 border-t border-neutral-200 px-4 py-3"
            >
                <p class="mb-2 text-xs font-semibold uppercase tracking-wide text-neutral-500">
                    {{ t('mail.attachments') }} ({{ detail.attachments.length }})
                </p>
                <div class="flex flex-wrap gap-2">
                    <button
                        v-for="att in detail.attachments"
                        :key="att.downloadId"
                        type="button"
                        class="flex items-center gap-1.5 rounded border border-neutral-200 bg-neutral-50 px-2.5 py-1.5 text-xs text-neutral-700 transition-colors hover:bg-neutral-100 hover:border-neutral-300"
                        :title="isPreviewable(att.mimeType) ? t('mail.preview.open') : t('mail.actions.download')"
                        @click="handleAttachmentClick(att)"
                    >
                        <Icon :name="attachmentIcon(att.mimeType)" size="14" class="flex-shrink-0 text-neutral-400" />
                        <span class="max-w-[180px] truncate">{{ att.filename }}</span>
                        <span class="text-neutral-400">({{ Math.round(att.size / 1024) }} Ko)</span>
                        <Icon
                            v-if="isPreviewable(att.mimeType)"
                            name="material-symbols:visibility-outline"
                            size="13"
                            class="flex-shrink-0 text-neutral-400"
                        />
                    </button>
                </div>
            </div>

            <MailAttachmentPreview
                v-if="previewAtt"
                v-model="previewOpen"
                :filename="previewAtt.filename"
                :mime-type="previewAtt.mimeType"
                :url="previewUrl"
                :loading="previewLoading"
                @download="downloadFromPreview"
            />
        </template>
    </div>
</template>
