import { headers } from "next/headers";
import { NextResponse } from "next/server";
import { auth } from "@/auth";
import { buildMultimodalMessages } from "@/lib/ai-event-messages";
import { getAiDisabledMessage, isAdminAiEnabled } from "@/lib/ai-feature-flags";
import { extractJsonFromText } from "@/lib/json-utils";
import { openRouterClient } from "@/lib/openrouter-client";
import { AiEventRequestSchema, AiEventResponseSchema } from "@/lib/types";

const MODEL = process.env.AI_MODEL ?? "openai/gpt-5.4-mini";

const buildSystemPrompt = () => `
You are an assistant that converts natural language and images into an ARRAY of calendar events.
TypeScript type:

{
  id?: string,
  title: string,
  description?: string,
  location?: string,
  url?: string,
  start: string, // ISO 8601 datetime with timezone, e.g. "2025-04-10T10:00:00-04:00"
  end?: string,
  allDay?: boolean,
  recurrenceRule?: string // valid iCal RRULE string like FREQ=WEEKLY;BYDAY=MO;INTERVAL=1
}[]

Rules:
  - If the user describes multiple events in one prompt, return multiple objects (one per event).
  - Always return a valid JSON array of objects, even if there's only one event.
  - Today is ${new Date().toISOString()}.
  - If no time is given, assume allDay event.
  - If no end time is given (and event is not allDay), default to 1 hour after start.
  - If multiple events are described, return multiple.
  - If recurrence is implied (e.g. "every Monday", "daily for 10 days", "monthly on the 15th"), generate a recurrenceRule.
  - When analyzing images, extract ALL visible event details: titles, dates, times, locations, descriptions.
  - If multiple images are provided, treat them all as sources for events (e.g. multiple flyer pages).
  - Output ONLY valid JSON (no prose).
`;

const callTextOnly = async (systemPrompt: string, prompt: string) => {
	const response = await openRouterClient.chat.send({
		chatRequest: {
			model: MODEL,
			messages: [
				{ role: "system", content: systemPrompt },
				{ role: "user", content: prompt },
			],
		},
	});

	const rawResponse = extractContentFromChatResponse(response);
	return { rawResponse };
};

/** Extract the text content from an OpenRouter chat.send response. */
const extractContentFromChatResponse = (response: unknown): string => {
	if (
		typeof response === "object" &&
		response !== null &&
		"choices" in response
	) {
		const choices = (
			response as {
				choices: Array<{ message: { content: string | unknown } }>;
			}
		).choices;
		const content = choices?.[0]?.message?.content;
		if (typeof content === "string") return content;
		if (content) return JSON.stringify(content);
	}
	throw new Error("Unexpected response format from AI chat API");
};

const callMultimodal = async (
	systemPrompt: string,
	prompt: string | undefined,
	images: string[],
) => {
	const messages = buildMultimodalMessages(systemPrompt, prompt, images);

	const response = await openRouterClient.chat.send({
		chatRequest: {
			model: MODEL,
			messages,
		},
	});

	const rawResponse = extractContentFromChatResponse(response);
	return { rawResponse };
};

export async function POST(request: Request) {
	if (!isAdminAiEnabled()) {
		return NextResponse.json(
			{ error: getAiDisabledMessage() },
			{ status: 403 },
		);
	}

	const session = await auth.api.getSession({
		headers: await headers(),
	});

	if (!session?.user) {
		return NextResponse.json(
			{ error: "Authentication required" },
			{ status: 401 },
		);
	}

	const body = await request.json();
	const parsedInput = AiEventRequestSchema.safeParse(body);

	if (!parsedInput.success) {
		return NextResponse.json(
			{
				error: "Invalid input",
				details: parsedInput.error.flatten().fieldErrors,
			},
			{ status: 400 },
		);
	}

	const { prompt, images } = parsedInput.data;
	const systemPrompt = buildSystemPrompt();

	try {
		const result =
			images && images.length > 0
				? await callMultimodal(systemPrompt, prompt, images)
				: await callTextOnly(systemPrompt, prompt ?? "");

		const rawJson = extractJsonFromText(result.rawResponse);
		const validated = AiEventResponseSchema.safeParse(rawJson);

		if (!validated.success) {
			console.error("AI response validation failed:", {
				issues: validated.error.flatten().fieldErrors,
			});

			return NextResponse.json(
				{
					error: "AI returned invalid event data",
					details: validated.error.flatten().fieldErrors,
				},
				{ status: 422 },
			);
		}

		return NextResponse.json(validated.data);
	} catch (error) {
		console.error("AI Event Creation Error:", error);
		return NextResponse.json(
			{ error: "Failed to process AI response. Please try again." },
			{ status: 500 },
		);
	}
}
