/**
 * Canvas module — the collaborative infinite canvas.
 *
 * This is the original rSpace canvas restructured as an rSpace module.
 * Routes are relative to the mount point (/:space/canvas in unified mode,
 * / in standalone mode).
 */

import { Hono } from "hono";
import { resolve } from "node:path";
import { renderShell } from "../../server/shell";
import { getModuleInfoList } from "../../shared/module";
import type { RSpaceModule } from "../../shared/module";

const DIST_DIR = resolve(import.meta.dir, "../../dist");

const routes = new Hono();

/**
 * Extract body content and scripts from the full canvas.html page.
 * Strips the shell chrome (header, tab-bar, welcome overlay) that renderShell provides,
 * and returns just the canvas-specific DOM + inline styles + module scripts.
 */
function extractCanvasContent(html: string): { body: string; styles: string; scripts: string } {
	// Extract inline <style> blocks from <head> (canvas CSS)
	const headMatch = html.match(/<head[^>]*>([\s\S]*?)<\/head>/i);
	const headContent = headMatch?.[1] || "";
	const styleBlocks: string[] = [];
	headContent.replace(/<style[^>]*>([\s\S]*?)<\/style>/gi, (match) => {
		styleBlocks.push(match);
		return "";
	});

	// Extract module script src from <head>
	const scriptSrcs: string[] = [];
	headContent.replace(/<script[^>]*\bsrc="([^"]+)"[^>]*>/gi, (_m, src: string) => {
		if (!src.includes("shell.js")) scriptSrcs.push(src);
		return "";
	});

	// Extract <body> content
	const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
	let bodyContent = bodyMatch?.[1] || "";

	// Strip shell chrome that renderShell already provides:
	// header, tab-bar (contains only a <rstack-tab-bar>), and welcome overlay.
	bodyContent = bodyContent
		.replace(/<header[\s\S]*?<\/header>/i, "")
		.replace(/<div class="rstack-tab-row"[^>]*>\s*<rstack-tab-bar[^>]*><\/rstack-tab-bar>\s*<\/div>/i, "")
		.replace(/<!--\s*Welcome overlay[\s\S]*?<\/div>\s*<\/div>\s*<\/div>/i, "");

	const styles = styleBlocks.join("\n");
	const scripts = scriptSrcs.map(s => `<script type="module" crossorigin src="${s}"></script>`).join("\n");

	return { body: bodyContent.trim(), styles, scripts };
}

// Cache the extracted canvas content (parsed once at startup)
let canvasContentCache: { body: string; styles: string; scripts: string } | null = null;

async function getCanvasContent(): Promise<{ body: string; styles: string; scripts: string }> {
	if (canvasContentCache) return canvasContentCache;

	// Prefer canvas-module.html (pre-extracted body partial)
	const moduleFile = Bun.file(resolve(DIST_DIR, "canvas-module.html"));
	if (await moduleFile.exists()) {
		canvasContentCache = {
			body: await moduleFile.text(),
			styles: "",
			scripts: `<script type="module" src="/canvas-module.js"></script>`,
		};
		return canvasContentCache;
	}

	// Fall back to extracting from full canvas.html
	const fullFile = Bun.file(resolve(DIST_DIR, "canvas.html"));
	if (await fullFile.exists()) {
		canvasContentCache = extractCanvasContent(await fullFile.text());
		return canvasContentCache;
	}

	return {
		body: `<div style="padding:2rem;text-align:center;color:#64748b;">Canvas loading...</div>`,
		styles: "",
		scripts: "",
	};
}

// GET / — serve the canvas page wrapped in shell
routes.get("/", async (c) => {
	const spaceSlug = c.req.param("space") || c.req.query("space") || "demo";
	const canvas = await getCanvasContent();

	const html = renderShell({
		title: `${spaceSlug} — Canvas | rSpace`,
		moduleId: "rspace",
		spaceSlug,
		body: canvas.body,
		modules: getModuleInfoList(),
		theme: "dark",
		styles: canvas.styles,
		scripts: canvas.scripts,
	});

	return c.html(html);
});

export const canvasModule: RSpaceModule = {
	id: "rspace",
	name: "rSpace",
	icon: "🎨",
	description: "Real-time collaborative canvas",
	scoping: { defaultScope: 'space', userConfigurable: false },
	routes,
	feeds: [
		{
			id: "shapes",
			name: "Canvas Shapes",
			kind: "data",
			description: "All shapes on this canvas layer — notes, embeds, arrows, etc.",
			filterable: true,
		},
		{
			id: "connections",
			name: "Shape Connections",
			kind: "data",
			description: "Arrow connections between shapes — the canvas graph",
		},
	],
	acceptsFeeds: ["economic", "trust", "data", "attention", "governance", "resource"],
	outputPaths: [
		{ path: "canvases", name: "Canvases", icon: "🎨", description: "Collaborative infinite canvases" },
	],
};
