/**
 * OpenResponses Feature Parity E2E Tests
 *
 * Tests for input_image, input_file, and client-side tools (Hosted Tools)
 * support in the OpenResponses `/v1/responses` endpoint.
 */

import { describe, it, expect } from "vitest";

describe("OpenResponses Feature Parity", () => {
  describe("Schema Validation", () => {
    it("should validate input_image with url source", async () => {
      const { InputImageContentPartSchema } = await import("./open-responses.schema.js");

      const validImage = {
        type: "input_image" as const,
        source: {
          type: "url" as const,
          url: "https://example.com/image.png",
        },
      };

      const result = InputImageContentPartSchema.safeParse(validImage);
      expect(result.success).toBe(true);
    });

    it("should validate input_image with base64 source", async () => {
      const { InputImageContentPartSchema } = await import("./open-responses.schema.js");

      const validImage = {
        type: "input_image" as const,
        source: {
          type: "base64" as const,
          media_type: "image/png" as const,
          data: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
        },
      };

      const result = InputImageContentPartSchema.safeParse(validImage);
      expect(result.success).toBe(true);
    });

    it("should reject input_image with invalid mime type", async () => {
      const { InputImageContentPartSchema } = await import("./open-responses.schema.js");

      const invalidImage = {
        type: "input_image" as const,
        source: {
          type: "base64" as const,
          media_type: "application/json" as const, // Not an image
          data: "SGVsbG8gV29ybGQh",
        },
      };

      const result = InputImageContentPartSchema.safeParse(invalidImage);
      expect(result.success).toBe(false);
    });

    it("should validate input_file with url source", async () => {
      const { InputFileContentPartSchema } = await import("./open-responses.schema.js");

      const validFile = {
        type: "input_file" as const,
        source: {
          type: "url" as const,
          url: "https://example.com/document.txt",
        },
      };

      const result = InputFileContentPartSchema.safeParse(validFile);
      expect(result.success).toBe(true);
    });

    it("should validate input_file with base64 source", async () => {
      const { InputFileContentPartSchema } = await import("./open-responses.schema.js");

      const validFile = {
        type: "input_file" as const,
        source: {
          type: "base64" as const,
          media_type: "text/plain" as const,
          data: "SGVsbG8gV29ybGQh",
          filename: "hello.txt",
        },
      };

      const result = InputFileContentPartSchema.safeParse(validFile);
      expect(result.success).toBe(true);
    });

    it("should validate tool definition", async () => {
      const { ToolDefinitionSchema } = await import("./open-responses.schema.js");

      const validTool = {
        type: "function" as const,
        function: {
          name: "get_weather",
          description: "Get the current weather",
          parameters: {
            type: "object",
            properties: {
              location: { type: "string" },
            },
            required: ["location"],
          },
        },
      };

      const result = ToolDefinitionSchema.safeParse(validTool);
      expect(result.success).toBe(true);
    });

    it("should reject tool definition without name", async () => {
      const { ToolDefinitionSchema } = await import("./open-responses.schema.js");

      const invalidTool = {
        type: "function" as const,
        function: {
          name: "", // Empty name
          description: "Get the current weather",
        },
      };

      const result = ToolDefinitionSchema.safeParse(invalidTool);
      expect(result.success).toBe(false);
    });
  });

  describe("CreateResponseBody Schema", () => {
    it("should validate request with input_image", async () => {
      const { CreateResponseBodySchema } = await import("./open-responses.schema.js");

      const validRequest = {
        model: "claude-sonnet-4-20250514",
        input: [
          {
            type: "message" as const,
            role: "user" as const,
            content: [
              {
                type: "input_image" as const,
                source: {
                  type: "url" as const,
                  url: "https://example.com/photo.jpg",
                },
              },
              {
                type: "input_text" as const,
                text: "What's in this image?",
              },
            ],
          },
        ],
      };

      const result = CreateResponseBodySchema.safeParse(validRequest);
      expect(result.success).toBe(true);
    });

    it("should validate request with client tools", async () => {
      const { CreateResponseBodySchema } = await import("./open-responses.schema.js");

      const validRequest = {
        model: "claude-sonnet-4-20250514",
        input: [
          {
            type: "message" as const,
            role: "user" as const,
            content: "What's the weather?",
          },
        ],
        tools: [
          {
            type: "function" as const,
            function: {
              name: "get_weather",
              description: "Get weather for a location",
              parameters: {
                type: "object",
                properties: {
                  location: { type: "string" },
                },
                required: ["location"],
              },
            },
          },
        ],
      };

      const result = CreateResponseBodySchema.safeParse(validRequest);
      expect(result.success).toBe(true);
    });

    it("should validate request with function_call_output for turn-based tools", async () => {
      const { CreateResponseBodySchema } = await import("./open-responses.schema.js");

      const validRequest = {
        model: "claude-sonnet-4-20250514",
        input: [
          {
            type: "function_call_output" as const,
            call_id: "call_123",
            output: '{"temperature": "72°F", "condition": "sunny"}',
          },
        ],
      };

      const result = CreateResponseBodySchema.safeParse(validRequest);
      expect(result.success).toBe(true);
    });

    it("should validate complete turn-based tool flow", async () => {
      const { CreateResponseBodySchema } = await import("./open-responses.schema.js");

      const turn1Request = {
        model: "claude-sonnet-4-20250514",
        input: [
          {
            type: "message" as const,
            role: "user" as const,
            content: "What's the weather in San Francisco?",
          },
        ],
        tools: [
          {
            type: "function" as const,
            function: {
              name: "get_weather",
              description: "Get weather for a location",
            },
          },
        ],
      };

      const turn1Result = CreateResponseBodySchema.safeParse(turn1Request);
      expect(turn1Result.success).toBe(true);

      // Turn 2: Client provides tool output
      const turn2Request = {
        model: "claude-sonnet-4-20250514",
        input: [
          {
            type: "function_call_output" as const,
            call_id: "call_123",
            output: '{"temperature": "72°F", "condition": "sunny"}',
          },
        ],
      };

      const turn2Result = CreateResponseBodySchema.safeParse(turn2Request);
      expect(turn2Result.success).toBe(true);
    });
  });

  describe("Response Resource Schema", () => {
    it("should validate response with function_call output", async () => {
      const { OutputItemSchema } = await import("./open-responses.schema.js");

      const functionCallOutput = {
        type: "function_call" as const,
        id: "msg_123",
        call_id: "call_456",
        name: "get_weather",
        arguments: '{"location": "San Francisco"}',
      };

      const result = OutputItemSchema.safeParse(functionCallOutput);
      expect(result.success).toBe(true);
    });
  });

  describe("buildAgentPrompt", () => {
    it("should convert function_call_output to tool entry", async () => {
      const { buildAgentPrompt } = await import("./openresponses-http.js");

      const result = buildAgentPrompt([
        {
          type: "function_call_output" as const,
          call_id: "call_123",
          output: '{"temperature": "72°F"}',
        },
      ]);

      // When there's only a tool output (no history), returns just the body
      expect(result.message).toBe('{"temperature": "72°F"}');
    });

    it("should handle mixed message and function_call_output items", async () => {
      const { buildAgentPrompt } = await import("./openresponses-http.js");

      const result = buildAgentPrompt([
        {
          type: "message" as const,
          role: "user" as const,
          content: "What's the weather?",
        },
        {
          type: "function_call_output" as const,
          call_id: "call_123",
          output: '{"temperature": "72°F"}',
        },
        {
          type: "message" as const,
          role: "user" as const,
          content: "Thanks!",
        },
      ]);

      // Should include both user messages and tool output
      expect(result.message).toContain("weather");
      expect(result.message).toContain("72°F");
      expect(result.message).toContain("Thanks");
    });
  });
});
