import { describe, expect, it } from "vitest";
import {
  extractOpenApiEndpoints,
  formatOpenApiConnectorSystemPrompt,
  formatSelectedOpenApiConnectorRawSpecPrompt,
} from "./openapi_utils";

describe("extractOpenApiEndpoints", () => {
  it("extracts endpoints from a JSON OpenAPI document", () => {
    const endpoints = extractOpenApiEndpoints({
      openapi: "3.0.3",
      info: {
        title: "Pets",
      },
      paths: {
        "/pets": {
          get: {
            summary: "List pets",
            operationId: "listPets",
            tags: ["pets"],
          },
          post: {
            summary: "Create pet",
            operationId: "createPet",
            tags: ["pets"],
          },
        },
      },
    });

    expect(endpoints).toEqual([
      {
        id: "listPets",
        method: "GET",
        path: "/pets",
        operationId: "listPets",
        summary: "List pets",
        description: null,
        tags: ["pets"],
      },
      {
        id: "createPet",
        method: "POST",
        path: "/pets",
        operationId: "createPet",
        summary: "Create pet",
        description: null,
        tags: ["pets"],
      },
    ]);
  });

  it("supports Swagger-style documents", () => {
    const endpoints = extractOpenApiEndpoints({
      swagger: "2.0",
      paths: {
        "/users/{id}": {
          delete: {
            summary: "Delete user",
          },
        },
      },
    });

    expect(endpoints).toEqual([
      {
        id: "DELETE /users/{id}",
        method: "DELETE",
        path: "/users/{id}",
        operationId: null,
        summary: "Delete user",
        description: null,
        tags: [],
      },
    ]);
  });

  it("formats a connector summary for the system prompt", () => {
    const prompt = formatOpenApiConnectorSystemPrompt({
      name: "Weather API",
      sourceUrl: "https://example.com/openapi.json",
      description: "Forecast data",
      specVersion: "3.1.0",
      endpoints: [
        {
          id: "getForecast",
          method: "GET",
          path: "/forecast",
          operationId: "getForecast",
          summary: "Get forecast",
          description: null,
          tags: ["weather"],
        },
      ],
    });

    expect(prompt).toContain("Connector: Weather API");
    expect(prompt).toContain("Spec URL: https://example.com/openapi.json");
    expect(prompt).toContain("- GET /forecast (getForecast) - Get forecast");
    expect(prompt).toContain(
      "Prefer these endpoints over inventing new API routes.",
    );
  });

  it("formats the full raw spec for a selected connector", () => {
    const prompt = formatSelectedOpenApiConnectorRawSpecPrompt({
      name: "Weather API",
      sourceUrl: "https://example.com/openapi.json",
      rawSpec: {
        openapi: "3.1.0",
        servers: [{ url: "https://api.example.com" }],
        components: {
          securitySchemes: {
            bearerAuth: {
              type: "http",
              scheme: "bearer",
            },
          },
          schemas: {
            ForecastRequest: {
              type: "object",
              required: ["city"],
              properties: {
                city: { type: "string" },
                unit: { type: "string", enum: ["metric", "imperial"] },
              },
            },
            ForecastResponse: {
              type: "object",
              properties: {
                temperature: { type: "number" },
                condition: { type: "string" },
              },
            },
          },
        },
        security: [{ bearerAuth: [] }],
        paths: {
          "/forecast": {
            post: {
              operationId: "createForecast",
              summary: "Create forecast request",
              parameters: [
                {
                  name: "x-region",
                  in: "header",
                  required: true,
                  schema: { type: "string" },
                },
              ],
              requestBody: {
                content: {
                  "application/json": {
                    schema: { $ref: "#/components/schemas/ForecastRequest" },
                  },
                },
              },
              responses: {
                "200": {
                  description: "Forecast response",
                  content: {
                    "application/json": {
                      schema: {
                        $ref: "#/components/schemas/ForecastResponse",
                      },
                    },
                  },
                },
              },
            },
          },
        },
      },
    });

    expect(prompt).toContain("# API Connector Raw Spec");
    expect(prompt).toContain("OpenAPI JSON:");
    expect(prompt).toContain('"openapi": "3.1.0"');
    expect(prompt).toContain('"servers": [');
    expect(prompt).toContain('"components": {');
    expect(prompt).toContain('"ForecastRequest": {');
    expect(prompt).toContain('"ForecastResponse": {');
    expect(prompt).toContain('"requestBody": {');
    expect(prompt).toContain('"responses": {');
  });
});
