import DOMPurify, { type Config as DOMPurifyConfig } from 'dompurify'

/**
 * Options de sanitization du corps HTML d'un mail.
 */
export type SanitizeMailHtmlOptions = {
    /**
     * Si true, les images distantes (http/https) sont affichées directement.
     * Par défaut false — les images distantes sont remplacées par un placeholder
     * cliquable pour éviter le tracking par pixel.
     */
    allowImages?: boolean
}

/**
 * Configuration DOMPurify bloquante pour les corps de mail.
 * - Bloque les balises dangereuses : script, iframe, object, embed, style, link, meta, form, input
 * - Bloque les attributs événements (on*) et les URI javascript:
 * - Autorise les URI data: uniquement pour les images (PNG/JPEG/GIF/WEBP) — images inline CID
 */
const DOMPURIFY_CONFIG: DOMPurifyConfig = {
    FORBID_TAGS: [
        'script',
        'iframe',
        'object',
        'embed',
        'style',
        'link',
        'meta',
        'form',
        'input',
        'button',
        'textarea',
        'select',
        'base',
        'applet',
    ],
    FORBID_ATTR: [
        'onerror',
        'onload',
        'onclick',
        'onmouseover',
        'onmouseout',
        'onmouseenter',
        'onmouseleave',
        'onfocus',
        'onblur',
        'onchange',
        'onsubmit',
        'onreset',
        'onkeydown',
        'onkeyup',
        'onkeypress',
        'ondblclick',
        'oncontextmenu',
        'onwheel',
        'ondrag',
        'ondrop',
        'oncopy',
        'oncut',
        'onpaste',
        'action',
        'formaction',
        'xlink:href',
    ],
    ALLOWED_URI_REGEXP: /^(?:https?|mailto|tel|cid|data:image\/(?:png|jpeg|gif|webp)(?:;base64,)?)(?::|$)/i,
    FORCE_BODY: true,
    WHOLE_DOCUMENT: false,
}

/**
 * Remplace les balises <img> avec src http(s):// par un bouton placeholder.
 * Le src original est stocké en data-mail-image-src pour permettre l'affichage
 * à la demande de l'utilisateur (Phase 5 — MailMessageViewer).
 */
function replaceRemoteImages(html: string): string {
    // Utiliser un DOMParser côté client uniquement (SSR-safe : le guard process.client
    // est géré par l'appelant dans un composant Vue — ce helper ne tourne que client-side)
    const parser = new DOMParser()
    const doc = parser.parseFromString(html, 'text/html')
    const images = doc.querySelectorAll('img')

    images.forEach((img) => {
        const src = img.getAttribute('src') ?? ''
        const isRemote = /^https?:\/\//i.test(src)
        if (!isRemote) return

        // Remplacer par un span cliquable (pas de <button> — DOMPurify le forbid)
        const placeholder = doc.createElement('span')
        placeholder.setAttribute('data-mail-image-src', src)
        placeholder.setAttribute('data-mail-image-placeholder', 'true')
        placeholder.setAttribute('title', src)
        placeholder.style.cssText = [
            'display: inline-flex',
            'align-items: center',
            'gap: 4px',
            'padding: 2px 6px',
            'border: 1px solid #d1d5db',
            'border-radius: 4px',
            'background: #f9fafb',
            'color: #6b7280',
            'font-size: 12px',
            'cursor: pointer',
            'user-select: none',
        ].join(';')
        placeholder.textContent = '[Image distante — cliquer pour afficher]'

        img.replaceWith(placeholder)
    })

    return doc.body.innerHTML
}

/**
 * Sanitize le HTML brut d'un corps de mail.
 *
 * - Bloque tous les vecteurs XSS connus (scripts, événements inline, iframes…)
 * - Par défaut, remplace les images distantes par un placeholder anti-tracking
 * - Utiliser allowImages: true uniquement si l'utilisateur a explicitement cliqué
 *   "Afficher les images" dans le lecteur de mail
 *
 * IMPORTANT : Cette fonction requiert un environnement navigateur (DOMParser, DOMPurify).
 * Ne pas appeler côté SSR — toujours dans un composant Vue avec `onMounted` ou dans
 * un computed côté client uniquement (`import.meta.client`).
 *
 * @param rawHtml - HTML brut tel que reçu de l'API backend
 * @param options - Options de sanitization
 * @returns HTML sanitizé, sûr pour injection via v-html
 */
export function sanitizeMailHtml(
    rawHtml: string,
    options: SanitizeMailHtmlOptions = {},
): string {
    if (!rawHtml || rawHtml.trim() === '') return ''

    // Étape 1 : DOMPurify — supprime tous les vecteurs dangereux
    const sanitized = DOMPurify.sanitize(rawHtml, DOMPURIFY_CONFIG) as string

    // Étape 2 : Remplacement images distantes (anti-tracking)
    if (!options.allowImages) {
        return replaceRemoteImages(sanitized)
    }

    return sanitized
}

/**
 * Vérifie si un élément HTML est un placeholder d'image généré par sanitizeMailHtml.
 * Utile dans MailMessageViewer pour gérer le clic "Afficher l'image".
 */
export function isMailImagePlaceholder(el: HTMLElement): boolean {
    return el.hasAttribute('data-mail-image-placeholder')
}

/**
 * Récupère le src original d'un placeholder d'image.
 */
export function getMailImageSrc(el: HTMLElement): string | null {
    return el.getAttribute('data-mail-image-src')
}
