import type { BunPlugin } from 'bun';
import React from 'react';
import { renderToString } from "react-dom/server";

import matter from 'gray-matter';
import { marked } from 'marked';
import { dbConnection } from "../src/db/index";

import { AppShell } from "../src/frontend/AppShell";
import { Post } from "../src/frontend/pages/post";

// TODO: Add better type handling for if Markdown parsing fails
const markdownLoader: BunPlugin = {
	name: 'markdown-loader',
	setup(build) {
		// Plugin implementation
		build.onLoad({filter: /\.md$/}, async args => {
			console.log("Loading markdown file:", args.path);
			const {data, content } = matter(await Bun.file(args.path).text());

			// Remove the title from content if it matches the frontmatter title to avoid duplicate H1s
			let processedContent = content;
			if (data.title) {
				const titleHeadingRegex = new RegExp(`^#\\s+${data.title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*$`, 'm');
				processedContent = content.replace(titleHeadingRegex, '').trim();
			}

			const bodyHtml = await marked.parse(processedContent);
			// AppShell is required here for rendering. If used at route level
			// Bun will only see an htmlBundle and fail to load anything
			// Validate required fields
			if (!data.title || !data.date) {
				throw new Error(`Markdown files must include title and date in frontmatter: ${args.path}`);
			}
			const meta = {
				title: data.title,
				date: new Date(data.date),
				readingTime: data.readingTime || `${Math.ceil(content.split(/\s+/).length / 200)} min read`
			};
			const renderedHtml = renderToString(<AppShell><Post meta={meta} children={bodyHtml} /></AppShell>);
			dbConnection.addPost(args.path, meta, bodyHtml); // Load the post to the database for dynamic querying

			// JSX Approach
			return {
        contents: renderedHtml,
				loader: 'html',
			};
		});
	},
};

export default markdownLoader;
