import { NextRequest, NextResponse } from "next/server";

type ChatRole = "user" | "assistant" | "system";

type IncomingMessage = {
  role: ChatRole;
  content: string;
};

type OpenRouterChoice = {
  message?: {
    content?: string | Array<{ type?: string; text?: string }>;
  };
};

type OpenRouterResponse = {
  choices?: OpenRouterChoice[];
  usage?: Record<string, unknown>;
  error?: {
    message?: string;
  };
};

type ChatRequestBody = {
  url?: string;
  apiKey?: string;
  model?: string;
  messages?: IncomingMessage[];
  appName?: string;
  siteUrl?: string;
  systemPrompt?: string;
  temperature?: number;
  maxTokens?: number;
};

function normalizeEndpoint(rawUrl: string): string {
  const trimmed = rawUrl.trim();
  if (!trimmed) return "https://openrouter.ai/api/v1/chat/completions";
  if (trimmed.endsWith("/chat/completions")) return trimmed;
  return `${trimmed.replace(/\/+$/, "")}/chat/completions`;
}

function normalizeMessages(
  messages: IncomingMessage[] | undefined,
  systemPrompt: string | undefined,
): IncomingMessage[] {
  const safeMessages =
    messages
      ?.filter(
        (m): m is IncomingMessage =>
          (m.role === "user" || m.role === "assistant" || m.role === "system") &&
          typeof m.content === "string" &&
          m.content.trim().length > 0,
      )
      .map((m) => ({ role: m.role, content: m.content.trim() })) ?? [];

  if (systemPrompt?.trim()) {
    return [{ role: "system", content: systemPrompt.trim() }, ...safeMessages];
  }
  return safeMessages;
}

function extractAssistantContent(payload: OpenRouterResponse): string {
  const first = payload.choices?.[0];
  const content = first?.message?.content;
  if (typeof content === "string") return content;
  if (Array.isArray(content)) {
    return content
      .map((part) => (part.type === "text" ? (part.text ?? "") : ""))
      .join("")
      .trim();
  }
  return "";
}

export async function POST(request: NextRequest) {
  let body: ChatRequestBody;
  try {
    body = (await request.json()) as ChatRequestBody;
  } catch {
    return NextResponse.json(
      { error: "Invalid JSON body" },
      { status: 400 },
    );
  }

  const apiKey = body.apiKey?.trim();
  const model = body.model?.trim();
  const messages = normalizeMessages(body.messages, body.systemPrompt);

  if (!apiKey) {
    return NextResponse.json(
      { error: "Missing OpenRouter API key" },
      { status: 400 },
    );
  }
  if (!model) {
    return NextResponse.json(
      { error: "Missing OpenRouter model" },
      { status: 400 },
    );
  }
  if (messages.length === 0) {
    return NextResponse.json(
      { error: "At least one non-empty message is required" },
      { status: 400 },
    );
  }

  const endpoint = normalizeEndpoint(
    body.url ?? "https://openrouter.ai/api/v1/chat/completions",
  );

  const upstreamBody = {
    model,
    messages,
    temperature:
      typeof body.temperature === "number" ? Math.max(0, Math.min(2, body.temperature)) : 0.2,
    max_tokens:
      typeof body.maxTokens === "number"
        ? Math.max(128, Math.min(32768, Math.round(body.maxTokens)))
        : 1200,
    stream: false,
  };

  try {
    const response = await fetch(endpoint, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${apiKey}`,
        ...(body.siteUrl?.trim()
          ? { "HTTP-Referer": body.siteUrl.trim() }
          : {}),
        ...(body.appName?.trim() ? { "X-Title": body.appName.trim() } : {}),
      },
      body: JSON.stringify(upstreamBody),
      cache: "no-store",
    });

    const payload = (await response.json()) as OpenRouterResponse;
    if (!response.ok) {
      return NextResponse.json(
        {
          error:
            payload.error?.message ??
            `OpenRouter request failed with status ${response.status}`,
        },
        { status: response.status },
      );
    }

    const content = extractAssistantContent(payload);
    if (!content) {
      return NextResponse.json(
        { error: "OpenRouter returned an empty response" },
        { status: 502 },
      );
    }

    return NextResponse.json({
      content,
      usage: payload.usage ?? null,
    });
  } catch (error) {
    return NextResponse.json(
      {
        error:
          error instanceof Error
            ? error.message
            : "Failed to reach OpenRouter",
      },
      { status: 500 },
    );
  }
}
