import { describe, it, expect, beforeEach } from "vitest";
import { TestOutputStrategy } from "./test-output.strategy";
import { VerificationContext } from "../interfaces";

describe("TestOutputStrategy", () => {
  let strategy: TestOutputStrategy;
  let baseContext: VerificationContext;

  beforeEach(() => {
    strategy = new TestOutputStrategy();
    baseContext = {
      taskId: "task-1",
      workspaceId: "workspace-1",
      agentId: "agent-1",
      claimMessage: "Implemented tests",
      filesChanged: ["src/feature.spec.ts"],
      outputLogs: "",
      previousAttempts: 0,
    };
  });

  describe("verify", () => {
    it("should pass when all tests pass", async () => {
      const context: VerificationContext = {
        ...baseContext,
        testResults: {
          total: 10,
          passed: 10,
          failed: 0,
          skipped: 0,
          coverage: 90,
        },
      };

      const result = await strategy.verify(context);

      expect(result.passed).toBe(true);
      expect(result.strategyName).toBe("test-output");
      expect(result.confidence).toBeGreaterThanOrEqual(90);
      expect(result.issues).toHaveLength(0);
    });

    it("should fail when tests fail", async () => {
      const context: VerificationContext = {
        ...baseContext,
        testResults: {
          total: 10,
          passed: 7,
          failed: 3,
          skipped: 0,
          coverage: 80,
        },
      };

      const result = await strategy.verify(context);

      expect(result.passed).toBe(false);
      expect(result.issues.some((i) => i.type === "test-failure")).toBe(true);
      expect(result.issues.some((i) => i.message.includes("3 test(s) failed"))).toBe(true);
    });

    it("should warn about skipped tests", async () => {
      const context: VerificationContext = {
        ...baseContext,
        testResults: {
          total: 10,
          passed: 8,
          failed: 0,
          skipped: 2,
          coverage: 85,
        },
      };

      const result = await strategy.verify(context);

      expect(result.passed).toBe(true);
      expect(result.issues.some((i) => i.severity === "warning")).toBe(true);
      expect(result.issues.some((i) => i.message.includes("2 test(s) skipped"))).toBe(true);
    });

    it("should fail when coverage is below threshold", async () => {
      const context: VerificationContext = {
        ...baseContext,
        testResults: {
          total: 10,
          passed: 10,
          failed: 0,
          skipped: 0,
          coverage: 70,
        },
      };

      const result = await strategy.verify(context);

      expect(result.passed).toBe(false);
      expect(result.issues.some((i) => i.type === "low-coverage")).toBe(true);
      expect(result.issues.some((i) => i.message.includes("70%"))).toBe(true);
    });

    it("should pass when coverage is at threshold", async () => {
      const context: VerificationContext = {
        ...baseContext,
        testResults: {
          total: 10,
          passed: 10,
          failed: 0,
          skipped: 0,
          coverage: 85,
        },
      };

      const result = await strategy.verify(context);

      expect(result.passed).toBe(true);
      expect(result.issues.filter((i) => i.type === "low-coverage")).toHaveLength(0);
    });

    it("should pass when no test results provided", async () => {
      const context: VerificationContext = {
        ...baseContext,
        testResults: undefined,
      };

      const result = await strategy.verify(context);

      expect(result.passed).toBe(true);
      expect(result.confidence).toBeGreaterThan(0);
    });

    it("should reduce confidence based on failure rate", async () => {
      const context: VerificationContext = {
        ...baseContext,
        testResults: {
          total: 10,
          passed: 5,
          failed: 5,
          skipped: 0,
          coverage: 80,
        },
      };

      const result = await strategy.verify(context);

      expect(result.passed).toBe(false);
      expect(result.confidence).toBeLessThan(50);
    });

    it("should have high confidence with perfect results", async () => {
      const context: VerificationContext = {
        ...baseContext,
        testResults: {
          total: 20,
          passed: 20,
          failed: 0,
          skipped: 0,
          coverage: 95,
        },
      };

      const result = await strategy.verify(context);

      expect(result.passed).toBe(true);
      expect(result.confidence).toBeGreaterThanOrEqual(95);
      expect(result.issues).toHaveLength(0);
    });
  });
});
