import { createContext } from "@kk/api/context";
import type { EmailMessage } from "@kk/api/email-queue";
import { appRouter } from "@kk/api/routers/index";
import { OpenAPIHandler } from "@orpc/openapi/fetch";
import { OpenAPIReferencePlugin } from "@orpc/openapi/plugins";
import { onError } from "@orpc/server";
import { RPCHandler } from "@orpc/server/fetch";
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
import { createFileRoute } from "@tanstack/react-router";

// Minimal CF Queue binding shape — mirrors the declaration in router.tsx / context.ts
type Queue = {
	send(
		message: EmailMessage,
		options?: { contentType?: string },
	): Promise<void>;
	sendBatch(
		messages: Array<{ body: EmailMessage }>,
		options?: { contentType?: string },
	): Promise<void>;
};

const rpcHandler = new RPCHandler(appRouter, {
	interceptors: [
		onError((error) => {
			console.error(error);
		}),
	],
});

const apiHandler = new OpenAPIHandler(appRouter, {
	plugins: [
		new OpenAPIReferencePlugin({
			schemaConverters: [new ZodToJsonSchemaConverter()],
		}),
	],
	interceptors: [
		onError((error) => {
			console.error(error);
		}),
	],
});

async function handle(ctx: { request: Request; context?: unknown }) {
	// emailQueue is threaded in via the fetch wrapper in server.ts
	const emailQueue = (ctx.context as { emailQueue?: Queue } | undefined)
		?.emailQueue;
	const context = await createContext({ req: ctx.request, emailQueue });

	const rpcResult = await rpcHandler.handle(ctx.request, {
		prefix: "/api/rpc",
		context,
	});
	if (rpcResult.response) return rpcResult.response;

	const apiResult = await apiHandler.handle(ctx.request, {
		prefix: "/api/rpc/api-reference",
		context,
	});
	if (apiResult.response) return apiResult.response;

	return new Response("Not found", { status: 404 });
}

export const Route = createFileRoute("/api/rpc/$")({
	server: {
		handlers: {
			HEAD: handle,
			GET: handle,
			POST: handle,
			PUT: handle,
			PATCH: handle,
			DELETE: handle,
		},
	},
});
