import { computed, createTextVNode, defineComponent, h, type VNode } from "vue";
import useHead from "@/useHead.ts";
import useAsyncState from "@/useAsyncState.ts";
import getDjAPI from "@/api.ts";
import getDomParser from "@/domParse.ts";
import { addCSS, css } from "../util.ts";

const style = css`
.byline {
    font-style: italic;
    color: gray;
}

h1 {
    color: var(--dj-palette1);
}

p {
    margin-bottom: 30px;
}
`;

export default defineComponent({
    name: "DjBlogEntry",
    props: {
        slug: {
            type: String,
            required: true,
        },
    },
    async setup(props) {
        addCSS('DjBlogEntry', style);

        const parseDom = getDomParser();

        const blogpostContent = useAsyncState(
            `dj-blog-article-content-${ props.slug }`,
            async ({ hostUrl }) => {
                const blogpostResponse = await fetch(`${hostUrl}/blog/content/${ props.slug }.html`);
                const result = await blogpostResponse.text();
                return result;
            },
        );

        const blogpostsMetadata = useAsyncState('article-metadata', ({ hostUrl }) => getDjAPI(hostUrl, '/blog-entries'));

        const blogpostMetadata = computed(() => blogpostsMetadata.result.value?.find(_ => _.slug === props.slug));

        useHead({
            title: () => blogpostMetadata.value?.title ?? '',
            metatags: () => blogpostMetadata.value ? [
                { name: 'title', content: blogpostMetadata.value.title },
                { name: 'author', content: 'Daniel Ledda' },
            ] : [],
        });

        function transformPostNode(node: Node): VNode | string {
            if (node.nodeType === node.ELEMENT_NODE) {
                const el = node as Element;
                const attrs: Record<string, string> = {};
                const children = [...node.childNodes].map((_) => transformPostNode(_));

                for (let i = 0; i < el.attributes.length; i++) {
                    const item = el.attributes.item(i);
                    if (item) {
                        attrs[item.name] = item.value;
                    }
                }

                return h((node as Element).tagName, attrs, children);
            } else {
                return createTextVNode(node.textContent ?? "");
            }
        }

        function PostContentTransformed() {
            if (blogpostContent.result.value) {
                const dom = parseDom(blogpostContent.result.value);
                return h("div", {}, [...dom.children].map((_) => transformPostNode(_)));
            }
            return <div>Blog post loading...</div>;
        }

        await Promise.allSettled([ blogpostContent.done, blogpostsMetadata.done ]);

        return () => <>
            { blogpostMetadata.value
                ? <>
                    <h1>{ blogpostMetadata.value.title }</h1>
                    <div class="byline">by Daniel Ledda, first published { new Date(blogpostMetadata.value.createdAt).toLocaleDateString() }</div>
                    <PostContentTransformed />
                </>
                : "Sorry, this blog post doesn't seem to exist."
            }
        </>;
    }
});

