import { MarkdownRenderer } from "./MarkdownRenderer.js";
import { BlogComments } from "./BlogComments.js";

/**
 * Decodes markdown payload from a JSON script element.
 *
 * @param {HTMLScriptElement | null} payloadEl
 * @returns {string}
 */
function readMarkdownPayload(payloadEl) {
    if (!payloadEl) return "";

    try {
        const parsed = JSON.parse(payloadEl.textContent || "\"\"");
        return typeof parsed === "string" ? parsed : "";
    } catch (error) {
        console.error("Failed to parse blog markdown payload", error);
        return "";
    }
}

/**
 * Wires copy buttons rendered by MarkdownRenderer.
 *
 * @param {ParentNode} container
 * @returns {void}
 */
function wireCopyButtons(container) {
    container.querySelectorAll(".md-copy-btn").forEach((button) => {
        button.addEventListener("click", (event) => {
            event.stopPropagation();
            const code = button.getAttribute("data-code");
            if (!code) return;

            navigator.clipboard.writeText(code).then(() => {
                const originalText = button.textContent;
                button.textContent = "✓";
                button.classList.add("copied");
                setTimeout(() => {
                    button.textContent = originalText;
                    button.classList.remove("copied");
                }, 2000);
            }).catch((error) => {
                console.error("Failed to copy code", error);
            });
        });
    });
}

/**
 * Renders blog markdown on static post pages using the shared renderer.
 *
 * @returns {void}
 */
function renderStaticBlogPost() {
    /** @type {HTMLElement | null} */
    const target = document.querySelector("[data-blog-post-content]");
    if (!target) return;

    /** @type {HTMLScriptElement | null} */
    const payload = document.querySelector("#blogPostMarkdown");
    const markdown = readMarkdownPayload(payload);

    target.innerHTML = MarkdownRenderer.render(markdown);
    MarkdownRenderer.applyImageScale(target);
    wireCopyButtons(target);
}

/**
 * Mounts Matrix-backed comments/reactions for the current blog post.
 *
 * @returns {Promise<void>}
 */
async function setupBlogComments() {
    /** @type {HTMLElement | null} */
    const mount = document.querySelector("[data-blog-comments]");
    if (!mount) return;

    const slug = window.location.pathname
        .split("/")
        .filter(Boolean)
        .pop() || "unknown";

    const homeserver = mount.dataset.matrixHomeserver || "https://chat.ruv.wtf";
    const roomAlias = mount.dataset.matrixRoom || "#general:chat.ruv.wtf";

    const comments = new BlogComments({
        homeserver,
        roomAlias,
        postSlug: slug
    });

    await comments.initialize(mount);
}

/**
 * Toggles the compact top bar when the hero logo scrolls out of view.
 *
 * @returns {void}
 */
function setupScrollTopBar() {
    const body = document.body;
    const bar = document.querySelector("[data-blog-scroll-topbar]");

    if (!bar) return;

    let lastScrollTop = 0;

    const applyState = () => {
        const scrollTop = body.scrollTop;
        const scrollingDown = scrollTop > lastScrollTop;
        lastScrollTop = scrollTop;

        if (scrollTop < 80) {
            body.classList.remove("blog-scrolled");
        } else if (scrollingDown) {
            body.classList.remove("blog-scrolled");
        } else {
            body.classList.add("blog-scrolled");
        }
    };
    body.addEventListener("scroll", applyState, { passive: true });
    applyState();
}

/**
 * Draws SVG bezier splines from the peek-card exec pins to the main blog card.
 *
 * @returns {void}
 */
function setupPeekSplines() {
    const svg = document.querySelector(".blog-post-splines");
    const layout = document.querySelector(".blog-post-layout");
    const card = document.querySelector(".blog-card");
    if (!svg || !layout || !card) return;

    const WIRE_COLOR = "#ffffff";
    const WIRE_OPACITY = "0.35";

    /**
     * Creates an SVG path element styled as an exec wire.
     *
     * @returns {SVGPathElement}
     */
    function makePath() {
        const p = document.createElementNS("http://www.w3.org/2000/svg", "path");
        p.setAttribute("fill", "none");
        p.setAttribute("stroke", WIRE_COLOR);
        p.setAttribute("stroke-width", "2.5");
        p.setAttribute("stroke-linecap", "round");
        p.style.opacity = WIRE_OPACITY;
        return p;
    }

    /**
     * Returns the center of an element relative to the layout container.
     *
     * @param {Element} el
     * @returns {{x: number, y: number}}
     */
    function centerOf(el) {
        const er = el.getBoundingClientRect();
        const lr = layout.getBoundingClientRect();
        return {
            x: er.left - lr.left + er.width / 2,
            y: er.top  - lr.top  + er.height / 2,
        };
    }

    /**
     * Returns the midpoint of a card's left or right edge relative to the layout.
     *
     * @param {Element} el
     * @param {'left'|'right'} side
     * @returns {{x: number, y: number}}
     */
    function edgeOf(el, side) {
        const er = el.getBoundingClientRect();
        const lr = layout.getBoundingClientRect();
        return {
            x: side === 'left' ? er.left - lr.left : er.right - lr.left,
            y: er.top - lr.top + 158,
        };
    }

    const pathPrev = makePath();
    const pathNext = makePath();
    svg.appendChild(pathPrev);
    svg.appendChild(pathNext);

    /** @returns {void} */
    function draw() {
        const lr = layout.getBoundingClientRect();
        svg.setAttribute("width",  String(lr.width));
        svg.setAttribute("height", String(lr.height));

        const prevPin  = document.querySelector("[data-peek-pin='prev-out']");
        const nextPin  = document.querySelector("[data-peek-pin='next-in']");
        const cardLeft  = edgeOf(card, "left");
        const cardRight = edgeOf(card, "right");

        if (prevPin) {
            const s = centerOf(prevPin);
            const e = cardLeft;
            const cp = Math.max(60, Math.abs(e.x - s.x) * 0.5);
            pathPrev.setAttribute("d", `M ${s.x} ${s.y} C ${s.x + cp} ${s.y} ${e.x - cp} ${e.y} ${e.x} ${e.y}`);
        } else {
            pathPrev.setAttribute("d", "");
        }

        if (nextPin) {
            const s = cardRight;
            const e = centerOf(nextPin);
            const cp = Math.max(60, Math.abs(e.x - s.x) * 0.5);
            pathNext.setAttribute("d", `M ${s.x} ${s.y} C ${s.x + cp} ${s.y} ${e.x - cp} ${e.y} ${e.x} ${e.y}`);
        } else {
            pathNext.setAttribute("d", "");
        }
    }

    draw();
    window.addEventListener("resize", draw, { passive: true });
    window.addEventListener("scroll", draw, { passive: true });
}

/**
 * Bootstraps static blog page behaviors.
 *
 * @returns {void}
 */
async function initializeBlogPage() {
    renderStaticBlogPost();
    setupScrollTopBar();
    setupPeekSplines();
    await setupBlogComments();
}

if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", initializeBlogPage, { once: true });
} else {
    initializeBlogPage();
}
