import { describe, it, expect } from "vitest";
import { ProgressInput, ProgressEntry } from "./events";

describe("ProgressInput", () => {
  it("accepts a valid step.start input", () => {
    const input = {
      v: 1,
      sessionId: "s1",
      prompt: "Create requirements for manufacturing",
      event: "step.start" as const,
      data: {
        skill: "erp-kit-app-1-requirements",
        context: { industry: "manufacturing" },
      },
    };
    const result = ProgressInput.safeParse(input);
    expect(result.success).toBe(true);
  });

  it("defaults conversation to empty array when omitted", () => {
    const input = {
      v: 1,
      sessionId: "s1",
      prompt: "Create screens for manufacturing",
      event: "decision" as const,
      data: {
        question: "Flat or tree?",
        choice: "tree",
        alternatives: ["flat"],
        rationale: "better UX",
      },
    };
    const result = ProgressInput.safeParse(input);
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.conversation).toEqual([]);
    }
  });

  it("rejects missing prompt", () => {
    const input = {
      v: 1,
      sessionId: "s1",
      event: "note" as const,
      data: { message: "test", tags: [] },
    };
    const result = ProgressInput.safeParse(input);
    expect(result.success).toBe(false);
  });

  it("rejects invalid event type", () => {
    const input = {
      v: 1,
      sessionId: "s1",
      prompt: "some prompt",
      event: "invalid.event",
      data: {},
    };
    const result = ProgressInput.safeParse(input);
    expect(result.success).toBe(false);
  });

  it("rejects mismatched event/data", () => {
    const input = {
      v: 1,
      sessionId: "s1",
      prompt: "some prompt",
      event: "step.start" as const,
      data: {
        question: "something",
        choice: "something",
        alternatives: [],
        rationale: "",
      },
    };
    const result = ProgressInput.safeParse(input);
    expect(result.success).toBe(false);
  });

  it("accepts all event types with correct data", () => {
    const events = [
      { event: "step.start", data: { skill: "s", context: {} } },
      { event: "step.complete", data: { status: "pass", summary: "done", artifacts: [] } },
      { event: "decision", data: { question: "q", choice: "c", alternatives: [], rationale: "r" } },
      { event: "agent.dispatch", data: { agentName: "a", task: "t", inputs: {} } },
      {
        event: "agent.result",
        data: { agentName: "a", status: "pass", outputs: {}, duration_ms: 100 },
      },
      { event: "artifact.create", data: { path: "f.md", type: "doc", operation: "create" } },
      { event: "validation", data: { command: "check", status: "pass", issues: [] } },
      { event: "error", data: { message: "err", recoverable: true } },
      { event: "note", data: { message: "note", tags: ["tag"] } },
    ];
    for (const { event, data } of events) {
      const result = ProgressInput.safeParse({
        v: 1,
        sessionId: "s1",
        prompt: "test prompt",
        event,
        data,
      });
      expect(result.success, `event "${event}" should be valid`).toBe(true);
    }
  });

  it("accepts conversation messages", () => {
    const input = {
      v: 1,
      sessionId: "s1",
      prompt: "test prompt",
      event: "decision" as const,
      conversation: [
        { role: "user" as const, message: "flat or tree?" },
        { role: "agent" as const, message: "I recommend tree" },
      ],
      data: {
        question: "layout",
        choice: "tree",
        alternatives: ["flat"],
        rationale: "better UX",
      },
    };
    const result = ProgressInput.safeParse(input);
    expect(result.success).toBe(true);
    if (result.success) {
      expect(result.data.conversation).toHaveLength(2);
    }
  });
});

describe("ProgressEntry", () => {
  it("accepts a full entry with timestamp and git", () => {
    const entry = {
      v: 1,
      timestamp: "2026-03-21T10:00:00.000Z",
      sessionId: "s1",
      prompt: "test prompt",
      event: "note" as const,
      git: { branch: "main", commit: "abc123" },
      conversation: [],
      data: { message: "test", tags: [] },
    };
    const result = ProgressEntry.safeParse(entry);
    expect(result.success).toBe(true);
  });

  it("rejects entry without timestamp", () => {
    const entry = {
      v: 1,
      sessionId: "s1",
      prompt: "test prompt",
      event: "note" as const,
      git: { branch: "main", commit: "abc123" },
      conversation: [],
      data: { message: "test", tags: [] },
    };
    const result = ProgressEntry.safeParse(entry);
    expect(result.success).toBe(false);
  });
});
