import { NextResponse } from "next/server";
import {
  extractModelOptions,
  getDefaultObjective5ModelOptions,
  getModelListEndpointCandidates,
} from "~/lib/lab2-chat";

type ModelsRouteRequestBody = {
  apiKey?: string;
  endpoint?: string;
};

const MODELS_TIMEOUT_MS = 15000;

export async function POST(request: Request) {
  let body: ModelsRouteRequestBody;

  try {
    body = (await request.json()) as ModelsRouteRequestBody;
  } catch {
    return NextResponse.json(
      {
        error: "The request body must be valid JSON.",
      },
      { status: 400 },
    );
  }

  const endpoint = body.endpoint?.trim();
  const apiKey = body.apiKey?.trim();

  if (!endpoint) {
    return NextResponse.json(
      {
        error: "An endpoint is required.",
      },
      { status: 400 },
    );
  }

  let candidates: string[];
  try {
    candidates = getModelListEndpointCandidates(endpoint);
  } catch {
    return NextResponse.json(
      {
        error: "The endpoint must be a valid URL.",
      },
      { status: 400 },
    );
  }

  const headers = {
    ...(apiKey
      ? {
          Authorization: `Bearer ${apiKey}`,
        }
      : {}),
  };

  for (const candidate of candidates) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), MODELS_TIMEOUT_MS);

    try {
      const response = await fetch(candidate, {
        headers,
        method: "GET",
        signal: controller.signal,
      });

      const responseText = await response.text();
      const parsed = JSON.parse(responseText) as unknown;

      if (!response.ok) {
        continue;
      }

      const models = extractModelOptions(parsed);
      return NextResponse.json({
        models:
          models.length > 0 ? models : getDefaultObjective5ModelOptions(),
      });
    } catch {
      continue;
    } finally {
      clearTimeout(timeoutId);
    }
  }

  return NextResponse.json(
    {
      error: "Could not load models from the endpoint.",
      models: getDefaultObjective5ModelOptions(),
    },
    { status: 502 },
  );
}
