import { randomUUID } from "node:crypto";
import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono";
import { z } from "zod";
import {
	extractDominantColor,
	fetchImageFromUrl,
} from "../services/image.service";
import { uploadImage } from "../services/storage.service";

const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"];
const MAX_SIZE = 5 * 1024 * 1024; // 5MB

const fromUrlSchema = z.object({ url: z.string().url("Invalid URL") });

const app = new Hono();

app.post("/from-url", zValidator("json", fromUrlSchema), async (c) => {
	const { url } = c.req.valid("json");
	try {
		const result = await fetchImageFromUrl(url);
		return c.json(result, 201);
	} catch (err) {
		const message = (err as Error).message;
		// Known validation errors from the service
		const isValidationError =
			message.startsWith("Invalid") ||
			message.startsWith("URL must") ||
			message.startsWith("File too") ||
			message.startsWith("HTTP ");
		return c.json({ error: message }, isValidationError ? 400 : 500);
	}
});

app.post("/", async (c) => {
	const body = await c.req.parseBody();
	const file = body.image;

	if (!file || typeof file === "string") {
		return c.json({ error: "No image file provided" }, 400);
	}

	// Validate file type
	if (!ALLOWED_TYPES.includes(file.type)) {
		return c.json(
			{ error: "Invalid file type. Accepted: jpeg, png, webp" },
			400,
		);
	}

	// Validate file size
	if (file.size > MAX_SIZE) {
		return c.json({ error: "File too large. Maximum size is 5MB" }, 400);
	}

	// Generate unique filename
	const ext =
		file.type.split("/")[1] === "jpeg" ? "jpg" : file.type.split("/")[1];
	const filename = `${Date.now()}-${randomUUID()}.${ext}`;

	// Upload to object storage
	const buffer = await file.arrayBuffer();
	await uploadImage(Buffer.from(buffer), filename, file.type);

	// Extract dominant color for adaptive background fill
	const dominantColor = await extractDominantColor(buffer);

	return c.json({ filename, dominantColor }, 201);
});

export { app as imageRoutes };
