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

import { copilotMessageSchema } from "./schema";

describe("copilotMessageSchema", () => {
  const validPayload = {
    id: "msg-123",
    chatId: "chat-456",
    diagramId: "diagram-789",
    diagramType: "bpmn",
    parts: [{ type: "text" as const, text: "Add a gateway node" }],
  };

  it("should accept a valid copilot message", () => {
    const result = copilotMessageSchema.safeParse(validPayload);
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.role).toBe("user");
    }
  });

  it("should accept all diagram types", () => {
    const types = ["bpmn", "er", "orgchart", "architecture", "sequence", "flowchart"];
    for (const type of types) {
      const result = copilotMessageSchema.safeParse({
        ...validPayload,
        diagramType: type,
      });
      expect(result.success).toBe(true);
    }
  });

  it("should reject invalid diagram type", () => {
    const result = copilotMessageSchema.safeParse({
      ...validPayload,
      diagramType: "invalid",
    });
    expect(result.success).toBe(false);
  });

  it("should reject missing diagramId", () => {
    const { diagramId: _, ...without } = validPayload;
    const result = copilotMessageSchema.safeParse(without);
    expect(result.success).toBe(false);
  });

  it("should reject missing parts", () => {
    const { parts: _, ...without } = validPayload;
    const result = copilotMessageSchema.safeParse(without);
    expect(result.success).toBe(false);
  });

  it("should reject empty parts text", () => {
    const result = copilotMessageSchema.safeParse({
      ...validPayload,
      parts: [{ type: "file", url: "x" }],
    });
    expect(result.success).toBe(false);
  });

  it("should default role to user", () => {
    const result = copilotMessageSchema.safeParse(validPayload);
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.role).toBe("user");
    }
  });

  it("should accept explicit role", () => {
    const result = copilotMessageSchema.safeParse({
      ...validPayload,
      role: "assistant",
    });
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.role).toBe("assistant");
    }
  });

  it("should reject invalid role", () => {
    const result = copilotMessageSchema.safeParse({
      ...validPayload,
      role: "system",
    });
    expect(result.success).toBe(false);
  });

  describe("selectedElements", () => {
    it("should accept valid selectedElements array", () => {
      const result = copilotMessageSchema.safeParse({
        ...validPayload,
        selectedElements: [
          { id: "n1", type: "activity", label: "Process order" },
          { id: "n2", type: "gateway-exclusive", label: "Valid?" },
        ],
      });
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.selectedElements).toHaveLength(2);
        expect(result.data.selectedElements![0]!.id).toBe("n1");
      }
    });

    it("should accept empty selectedElements array", () => {
      const result = copilotMessageSchema.safeParse({
        ...validPayload,
        selectedElements: [],
      });
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.selectedElements).toHaveLength(0);
      }
    });

    it("should accept missing selectedElements (optional)", () => {
      const result = copilotMessageSchema.safeParse(validPayload);
      expect(result.success).toBe(true);
      if (result.success) {
        expect(result.data.selectedElements).toBeUndefined();
      }
    });

    it("should reject selectedElements with missing required fields", () => {
      const result = copilotMessageSchema.safeParse({
        ...validPayload,
        selectedElements: [{ id: "n1" }],
      });
      expect(result.success).toBe(false);
    });

    it("should reject non-array selectedElements", () => {
      const result = copilotMessageSchema.safeParse({
        ...validPayload,
        selectedElements: "n1",
      });
      expect(result.success).toBe(false);
    });

    it("should reject selectedElements with empty string fields", () => {
      const result = copilotMessageSchema.safeParse({
        ...validPayload,
        selectedElements: [{ id: "", type: "activity", label: "Test" }],
      });
      expect(result.success).toBe(false);
    });
  });
});
