import { describe, it, expect, beforeEach, vi } from "vitest";
import { EmbeddingService } from "./embedding.service";
import { PrismaService } from "../../prisma/prisma.service";

describe("EmbeddingService", () => {
  let service: EmbeddingService;
  let prismaService: PrismaService;

  beforeEach(() => {
    prismaService = {
      $executeRaw: vi.fn(),
      knowledgeEmbedding: {
        deleteMany: vi.fn(),
      },
    } as unknown as PrismaService;

    service = new EmbeddingService(prismaService);
  });

  describe("isConfigured", () => {
    it("should return false when OPENAI_API_KEY is not set", () => {
      const originalEnv = process.env["OPENAI_API_KEY"];
      delete process.env["OPENAI_API_KEY"];

      expect(service.isConfigured()).toBe(false);

      if (originalEnv) {
        process.env["OPENAI_API_KEY"] = originalEnv;
      }
    });

    it("should return true when OPENAI_API_KEY is set", () => {
      const originalEnv = process.env["OPENAI_API_KEY"];
      process.env["OPENAI_API_KEY"] = "test-key";

      expect(service.isConfigured()).toBe(true);

      if (originalEnv) {
        process.env["OPENAI_API_KEY"] = originalEnv;
      } else {
        delete process.env["OPENAI_API_KEY"];
      }
    });
  });

  describe("prepareContentForEmbedding", () => {
    it("should combine title and content with title weighting", () => {
      const title = "Test Title";
      const content = "Test content goes here";

      const result = service.prepareContentForEmbedding(title, content);

      expect(result).toContain(title);
      expect(result).toContain(content);
      // Title should appear twice for weighting
      expect(result.split(title).length - 1).toBe(2);
    });

    it("should handle empty content", () => {
      const title = "Test Title";
      const content = "";

      const result = service.prepareContentForEmbedding(title, content);

      expect(result).toBe(`${title}\n\n${title}`);
    });
  });

  describe("generateAndStoreEmbedding", () => {
    it("should skip generation when not configured", async () => {
      const originalEnv = process.env["OPENAI_API_KEY"];
      delete process.env["OPENAI_API_KEY"];

      await service.generateAndStoreEmbedding("test-id", "test content");

      expect(prismaService.$executeRaw).not.toHaveBeenCalled();

      if (originalEnv) {
        process.env["OPENAI_API_KEY"] = originalEnv;
      }
    });
  });

  describe("deleteEmbedding", () => {
    it("should delete embedding for entry", async () => {
      const entryId = "test-entry-id";

      await service.deleteEmbedding(entryId);

      expect(prismaService.knowledgeEmbedding.deleteMany).toHaveBeenCalledWith({
        where: { entryId },
      });
    });
  });

  describe("batchGenerateEmbeddings", () => {
    it("should return 0 when not configured", async () => {
      const originalEnv = process.env["OPENAI_API_KEY"];
      delete process.env["OPENAI_API_KEY"];

      const entries = [
        { id: "1", content: "content 1" },
        { id: "2", content: "content 2" },
      ];

      const result = await service.batchGenerateEmbeddings(entries);

      expect(result).toBe(0);

      if (originalEnv) {
        process.env["OPENAI_API_KEY"] = originalEnv;
      }
    });
  });
});
