import { describe, it, expect } from "vitest";
import {
  CONTENT_TOPICS,
  AGGREGATE_TYPES,
  EVENT_TYPES,
  getTopicForEvent,
  buildEventPayload,
} from "./events.js";

describe("events", () => {
  describe("CONTENT_TOPICS", () => {
    it("should have 4 aggregate topics", () => {
      expect(Object.keys(CONTENT_TOPICS)).toHaveLength(4);
      expect(CONTENT_TOPICS.TEXTBOOK).toBe("edu.content.textbook.events");
      expect(CONTENT_TOPICS.CHAPTER).toBe("edu.content.chapter.events");
      expect(CONTENT_TOPICS.KNOWLEDGE_POINT).toBe(
        "edu.content.knowledge_point.events",
      );
      expect(CONTENT_TOPICS.QUESTION).toBe("edu.content.question.events");
    });
  });

  describe("AGGREGATE_TYPES", () => {
    it("should have 4 aggregate types", () => {
      expect(AGGREGATE_TYPES.TEXTBOOK).toBe("Textbook");
      expect(AGGREGATE_TYPES.CHAPTER).toBe("Chapter");
      expect(AGGREGATE_TYPES.KNOWLEDGE_POINT).toBe("KnowledgePoint");
      expect(AGGREGATE_TYPES.QUESTION).toBe("Question");
    });
  });

  describe("EVENT_TYPES", () => {
    it("should have 15 event types", () => {
      expect(Object.keys(EVENT_TYPES)).toHaveLength(15);
    });
  });

  describe("getTopicForEvent", () => {
    it("should route textbook events to textbook topic", () => {
      expect(getTopicForEvent(EVENT_TYPES.TEXTBOOK_CREATED)).toBe(
        CONTENT_TOPICS.TEXTBOOK,
      );
      expect(getTopicForEvent(EVENT_TYPES.TEXTBOOK_UPDATED)).toBe(
        CONTENT_TOPICS.TEXTBOOK,
      );
      expect(getTopicForEvent(EVENT_TYPES.TEXTBOOK_PUBLISHED)).toBe(
        CONTENT_TOPICS.TEXTBOOK,
      );
      expect(getTopicForEvent(EVENT_TYPES.TEXTBOOK_ARCHIVED)).toBe(
        CONTENT_TOPICS.TEXTBOOK,
      );
    });

    it("should route chapter events to chapter topic", () => {
      expect(getTopicForEvent(EVENT_TYPES.CHAPTER_CREATED)).toBe(
        CONTENT_TOPICS.CHAPTER,
      );
      expect(getTopicForEvent(EVENT_TYPES.CHAPTER_DELETED)).toBe(
        CONTENT_TOPICS.CHAPTER,
      );
    });

    it("should route KP events to knowledge_point topic", () => {
      expect(getTopicForEvent(EVENT_TYPES.KP_CREATED)).toBe(
        CONTENT_TOPICS.KNOWLEDGE_POINT,
      );
      expect(getTopicForEvent(EVENT_TYPES.KP_PREREQUISITE_ADDED)).toBe(
        CONTENT_TOPICS.KNOWLEDGE_POINT,
      );
    });

    it("should route question events to question topic", () => {
      expect(getTopicForEvent(EVENT_TYPES.QUESTION_CREATED)).toBe(
        CONTENT_TOPICS.QUESTION,
      );
      expect(getTopicForEvent(EVENT_TYPES.QUESTION_PUBLISHED)).toBe(
        CONTENT_TOPICS.QUESTION,
      );
    });

    it("should return fallback topic for unknown events", () => {
      expect(getTopicForEvent("unknown.event")).toBe("edu.content.fallback");
    });
  });

  describe("buildEventPayload", () => {
    it("should build payload with event_id, aggregate_id, event_type, occurred_at, action", () => {
      const payload = buildEventPayload("textbook.created", "tb-1", {
        title: "Test",
      });

      expect(payload.event_id).toBeDefined();
      expect(payload.aggregate_id).toBe("tb-1");
      expect(payload.event_type).toBe("edu.content.textbook.created");
      expect(payload.occurred_at).toBeGreaterThan(0);
      expect(payload.action).toBe("created");
      expect(payload.title).toBe("Test");
    });

    it("should extract action from event type with multiple dots", () => {
      const payload = buildEventPayload(
        "knowledge_point.prerequisite_added",
        "kp-1",
        {},
      );
      expect(payload.action).toBe("prerequisite_added");
      expect(payload.event_type).toBe(
        "edu.content.knowledge_point.prerequisite_added",
      );
    });
  });
});
