/**
 * Swag module — design tool for print-ready swag (stickers, posters, tees).
 *
 * Ported from /opt/apps/swag-designer/ (Next.js → Hono).
 * Uses Sharp for image processing. No database needed (filesystem storage).
 */

import { Hono } from "hono";
import { randomUUID } from "node:crypto";
import { mkdir, writeFile, readFile, readdir, stat } from "node:fs/promises";
import { join } from "node:path";
import { getProduct, PRODUCTS } from "./products";
import { processImage } from "./process-image";
import { renderShell } from "../../server/shell";
import { getModuleInfoList } from "../../shared/module";
import type { RSpaceModule } from "../../shared/module";
import { renderLanding } from "./landing";

const routes = new Hono();

const ARTIFACTS_DIR = process.env.SWAG_ARTIFACTS_DIR || "/tmp/swag-artifacts";

// ── GET /api/products — List available product templates ──
routes.get("/api/products", (c) => {
	const products = Object.values(PRODUCTS).map((p) => ({
		id: p.id,
		name: p.name,
		description: p.description,
		printArea: p.printArea,
		dpi: p.dpi,
		bleedMm: p.bleedMm,
		widthPx: p.widthPx,
		heightPx: p.heightPx,
		productType: p.productType,
		substrates: p.substrates,
		requiredCapabilities: p.requiredCapabilities,
		finish: p.finish,
		...(p.printful ? { printful: p.printful } : {}),
	}));
	return c.json({ products });
});

// ── POST /api/generate — Preview without persistence ──
routes.post("/api/generate", async (c) => {
	try {
		const formData = await c.req.formData();
		const imageFile = formData.get("image") as File | null;
		const productId = formData.get("product") as string | null;

		if (!imageFile) return c.json({ error: "image file is required" }, 400);
		if (!productId) return c.json({ error: "product is required (sticker, poster, tee)" }, 400);

		const product = getProduct(productId);
		if (!product) return c.json({ error: `Unknown product: ${productId}` }, 400);

		const inputBuffer = Buffer.from(await imageFile.arrayBuffer());
		const result = await processImage(inputBuffer, product);

		return new Response(new Uint8Array(result.buffer), {
			status: 200,
			headers: {
				"Content-Type": "image/png",
				"Content-Disposition": `attachment; filename="${productId}-print-ready.png"`,
				"Content-Length": String(result.sizeBytes),
				"X-Width-Px": String(result.widthPx),
				"X-Height-Px": String(result.heightPx),
				"X-DPI": String(result.dpi),
			},
		});
	} catch (error) {
		console.error("Generate error:", error);
		return c.json({ error: error instanceof Error ? error.message : "Processing failed" }, 500);
	}
});

// ── POST /api/artifact — Create artifact with persistence ──
routes.post("/api/artifact", async (c) => {
	try {
		const formData = await c.req.formData();
		const imageFile = formData.get("image") as File | null;
		const productId = formData.get("product") as string | null;

		const title = (formData.get("title") as string) || "Untitled Design";
		const description = formData.get("description") as string | null;
		const creatorId = formData.get("creator_id") as string | null;
		const creatorName = formData.get("creator_name") as string | null;
		const creatorWallet = formData.get("creator_wallet") as string | null;
		const sourceSpace = formData.get("source_space") as string | null;
		const license = formData.get("license") as string | null;
		const tagsRaw = formData.get("tags") as string | null;
		const tags = tagsRaw ? tagsRaw.split(",").map((t) => t.trim()) : [];
		const creatorSharePct = parseFloat((formData.get("creator_share_pct") as string) || "25");
		const communitySharePct = parseFloat((formData.get("community_share_pct") as string) || "10");

		if (!imageFile) return c.json({ error: "image file is required" }, 400);
		if (!productId || !getProduct(productId)) {
			return c.json({ error: `product is required. Available: ${Object.keys(PRODUCTS).join(", ")}` }, 400);
		}

		const product = getProduct(productId)!;
		const inputBuffer = Buffer.from(await imageFile.arrayBuffer());
		const result = await processImage(inputBuffer, product);

		// Store artifact
		const artifactId = randomUUID();
		const artifactDir = join(ARTIFACTS_DIR, artifactId);
		await mkdir(artifactDir, { recursive: true });

		const filename = `${productId}-print-ready.png`;
		await writeFile(join(artifactDir, filename), result.buffer);
		await writeFile(join(artifactDir, `original-${imageFile.name}`), inputBuffer);

		// Build artifact envelope
		const proto = c.req.header("x-forwarded-proto") || "https";
		const host = c.req.header("host") || "rswag.online";
		const baseUrl = `${proto}://${host}`;
		const renderTargetKey = `${product.id}-${result.format}`;

		// Build the URL — in unified mode, we're mounted under /:space/swag
		const path = c.req.path.replace("/api/artifact", "");
		const mountBase = c.req.url.includes("/swag/") ? c.req.url.split("/swag/")[0] + "/swag" : "";
		const fileUrl = mountBase ? `${baseUrl}${mountBase}/api/artifact/${artifactId}/file` : `${baseUrl}/api/artifact/${artifactId}/file`;

		const artifact = {
			id: artifactId,
			schema_version: "1.0",
			type: "print-ready",
			origin: "rswag.online",
			source_space: sourceSpace || null,
			creator: {
				id: creatorId || "anonymous",
				...(creatorName ? { name: creatorName } : {}),
				...(creatorWallet ? { wallet: creatorWallet } : {}),
			},
			created_at: new Date().toISOString(),
			...(license ? { license } : {}),
			payload: {
				title,
				...(description ? { description } : {
					description: `${product.name} design — ${result.widthPx}x${result.heightPx}px at ${result.dpi}dpi`,
				}),
				...(tags.length > 0 ? { tags } : {}),
			},
			spec: {
				product_type: product.productType,
				dimensions: {
					width_mm: product.printArea.widthMm,
					height_mm: product.printArea.heightMm,
					bleed_mm: product.bleedMm,
				},
				color_space: "CMYK",
				dpi: product.dpi,
				binding: "none",
				finish: product.finish,
				substrates: product.substrates,
				required_capabilities: product.requiredCapabilities,
			},
			render_targets: {
				[renderTargetKey]: {
					url: fileUrl,
					format: result.format,
					dpi: result.dpi,
					file_size_bytes: result.sizeBytes,
					notes: `${product.name} print-ready file. ${result.widthPx}x${result.heightPx}px.`,
				},
			},
			pricing: {
				creator_share_pct: creatorSharePct,
				community_share_pct: communitySharePct,
			},
			next_actions: [
				{ tool: "rcart.online", action: "list-for-sale", label: "Sell in community shop", endpoint: "/api/catalog/ingest", method: "POST" },
				{ tool: "rswag.online", action: "edit-design", label: "Edit design", endpoint: "/editor", method: "GET" },
				{ tool: "rfiles.online", action: "archive", label: "Save to files", endpoint: "/api/v1/files/import", method: "POST" },
			],
		};

		await writeFile(join(artifactDir, "artifact.json"), JSON.stringify(artifact, null, 2));

		return c.json(artifact, 201);
	} catch (error) {
		console.error("Artifact generation error:", error);
		return c.json({ error: error instanceof Error ? error.message : "Artifact generation failed" }, 500);
	}
});

// ── GET /api/artifact/:id/file — Download render target ──
routes.get("/api/artifact/:id/file", async (c) => {
	const id = c.req.param("id");
	if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id)) {
		return c.json({ error: "Invalid artifact ID" }, 400);
	}

	const artifactDir = join(ARTIFACTS_DIR, id);
	try { await stat(artifactDir); } catch { return c.json({ error: "Artifact not found" }, 404); }

	const files = await readdir(artifactDir);
	const printFile = files.find((f) => f.includes("print-ready") && (f.endsWith(".png") || f.endsWith(".tiff")));
	if (!printFile) return c.json({ error: "Print file not found" }, 404);

	const buffer = await readFile(join(artifactDir, printFile));
	const contentType = printFile.endsWith(".tiff") ? "image/tiff" : "image/png";

	return new Response(new Uint8Array(buffer), {
		status: 200,
		headers: {
			"Content-Type": contentType,
			"Content-Disposition": `inline; filename="${printFile}"`,
			"Content-Length": String(buffer.length),
		},
	});
});

// ── GET /api/artifact/:id — Get artifact metadata ──
routes.get("/api/artifact/:id", async (c) => {
	const id = c.req.param("id");
	if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id)) {
		return c.json({ error: "Invalid artifact ID" }, 400);
	}

	const artifactPath = join(ARTIFACTS_DIR, id, "artifact.json");
	try {
		const data = await readFile(artifactPath, "utf-8");
		return c.json(JSON.parse(data));
	} catch {
		return c.json({ error: "Artifact not found" }, 404);
	}
});

// ── Page route: swag designer ──
routes.get("/", (c) => {
	const space = c.req.param("space") || "demo";
	return c.html(renderShell({
		title: `Swag Designer | rSpace`,
		moduleId: "rswag",
		spaceSlug: space,
		modules: getModuleInfoList(),
		theme: "dark",
		body: `<folk-swag-designer space="${space}"></folk-swag-designer>`,
		scripts: `<script type="module" src="/modules/rswag/folk-swag-designer.js?v=2"></script>`,
		styles: `<link rel="stylesheet" href="/modules/rswag/swag.css?v=2">`,
	}));
});

export const swagModule: RSpaceModule = {
	id: "rswag",
	name: "rSwag",
	icon: "🎨",
	description: "Design print-ready swag: stickers, posters, tees",
	scoping: { defaultScope: 'global', userConfigurable: true },
	routes,
	landingPage: renderLanding,
	standaloneDomain: "rswag.online",
	feeds: [
		{
			id: "designs",
			name: "Designs",
			kind: "resource",
			description: "Print-ready design artifacts for stickers, posters, and tees",
			filterable: true,
		},
		{
			id: "merch-orders",
			name: "Merch Orders",
			kind: "economic",
			description: "Merchandise order events and fulfillment tracking",
		},
	],
	acceptsFeeds: ["economic", "resource"],
	outputPaths: [
		{ path: "merchandise", name: "Merchandise", icon: "👕", description: "Print-ready swag designs" },
	],
};
