'use strict';

import { Controller } from "@hotwired/stimulus";

/**
 * Reads the `flashes` cookie (written by FOSHttpCacheBundle's
 * FlashMessageListener during the previous request), fetches a Turbo Stream
 * for each flash, and lets Turbo splice the returned markup into the DOM.
 *
 * Stays dumb on purpose: every flash type (modal, notification, banner) is
 * a fully self-describing Turbo Stream — the stream template declares the
 * action + target. Adding a flash type is template-only; no JS changes.
 *
 * Modal flashes stream into the `<turbo-frame id="modal">` inside the
 * Cms:Modal component; modal.ts has a MutationObserver on that frame that
 * opens the dialog as soon as content appears.
 */
export default class extends Controller {
    static values = { url: String };
    declare readonly urlValue: string;

    connect() {
        const flashes = this.getCookie("flashes");
        if (!flashes) return;

        let data: Record<string, unknown>;
        try {
            data = JSON.parse(decodeURIComponent(flashes.replace(/\+/g, " ")));
        } catch (e) {
            console.error("Failed to parse flashes cookie", e);
            return;
        }

        this.clearCookie("flashes");

        Object.entries(data).forEach(([type, messages]) => {
            if (!Array.isArray(messages)) return;
            messages.forEach((message) => this.renderFlash(type, message));
        });
    }

    private async renderFlash(type: string, message: unknown) {
        const url = new URL(this.urlValue, window.location.origin);
        url.searchParams.set("type", type);

        if (typeof message === "object" && message !== null) {
            Object.entries(message as Record<string, unknown>).forEach(([k, v]) => {
                if (v !== null && v !== undefined) url.searchParams.set(k, String(v));
            });
        } else if (typeof message === "string") {
            url.searchParams.set("text", message);
        }

        const response = await fetch(url.toString(), {
            headers: { Accept: "text/vnd.turbo-stream.html" },
        });
        if (!response.ok) return;

        const stream = await response.text();
        // Turbo picks up <turbo-stream> custom elements as they enter the
        // DOM; the template decides action + target.
        document.body.insertAdjacentHTML("beforeend", stream);
    }

    private getCookie(name: string): string | false {
        for (const c of document.cookie.split(";")) {
            const t = c.trim();
            if (t.startsWith(name + "=")) return t.substring(name.length + 1);
        }
        return false;
    }

    private clearCookie(name: string) {
        document.cookie = `${name}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
    }
}
