import { describe, it, expect, beforeEach, vi } from "vitest";
import { Test, TestingModule } from "@nestjs/testing";
import { UnauthorizedException } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { CoordinatorIntegrationController } from "./coordinator-integration.controller";
import { CoordinatorIntegrationService } from "./coordinator-integration.service";
import { ApiKeyGuard } from "../common/guards/api-key.guard";

/**
 * Security tests for CoordinatorIntegrationController
 *
 * These tests verify that all coordinator endpoints require authentication
 * and reject requests without valid API keys.
 */
describe("CoordinatorIntegrationController - Security", () => {
  let controller: CoordinatorIntegrationController;
  let guard: ApiKeyGuard;

  const mockService = {
    createJob: vi.fn(),
    updateJobStatus: vi.fn(),
    updateJobProgress: vi.fn(),
    completeJob: vi.fn(),
    failJob: vi.fn(),
    getJobDetails: vi.fn(),
    getIntegrationHealth: vi.fn(),
  };

  const mockConfigService = {
    get: vi.fn().mockReturnValue("test-api-key-12345"),
  };

  beforeEach(async () => {
    vi.clearAllMocks();

    const module: TestingModule = await Test.createTestingModule({
      controllers: [CoordinatorIntegrationController],
      providers: [
        { provide: CoordinatorIntegrationService, useValue: mockService },
        { provide: ConfigService, useValue: mockConfigService },
        ApiKeyGuard,
      ],
    }).compile();

    controller = module.get<CoordinatorIntegrationController>(CoordinatorIntegrationController);
    guard = module.get<ApiKeyGuard>(ApiKeyGuard);
  });

  describe("Authentication Requirements", () => {
    it("should have ApiKeyGuard applied to controller", () => {
      const guards = Reflect.getMetadata("__guards__", CoordinatorIntegrationController);
      expect(guards).toBeDefined();
      expect(guards).toContain(ApiKeyGuard);
    });

    it("POST /coordinator/jobs should require authentication", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({ headers: {} }),
        }),
      };

      expect(() => guard.canActivate(mockContext as never)).toThrow(UnauthorizedException);
    });

    it("PATCH /coordinator/jobs/:id/status should require authentication", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({ headers: {} }),
        }),
      };

      expect(() => guard.canActivate(mockContext as never)).toThrow(UnauthorizedException);
    });

    it("PATCH /coordinator/jobs/:id/progress should require authentication", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({ headers: {} }),
        }),
      };

      expect(() => guard.canActivate(mockContext as never)).toThrow(UnauthorizedException);
    });

    it("POST /coordinator/jobs/:id/complete should require authentication", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({ headers: {} }),
        }),
      };

      expect(() => guard.canActivate(mockContext as never)).toThrow(UnauthorizedException);
    });

    it("POST /coordinator/jobs/:id/fail should require authentication", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({ headers: {} }),
        }),
      };

      expect(() => guard.canActivate(mockContext as never)).toThrow(UnauthorizedException);
    });

    it("GET /coordinator/jobs/:id should require authentication", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({ headers: {} }),
        }),
      };

      expect(() => guard.canActivate(mockContext as never)).toThrow(UnauthorizedException);
    });

    it("GET /coordinator/health should require authentication", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({ headers: {} }),
        }),
      };

      expect(() => guard.canActivate(mockContext as never)).toThrow(UnauthorizedException);
    });
  });

  describe("Valid Authentication", () => {
    it("should allow requests with valid API key", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({
            headers: { "x-api-key": "test-api-key-12345" },
          }),
        }),
      };

      const result = guard.canActivate(mockContext as never);
      expect(result).toBe(true);
    });

    it("should reject requests with invalid API key", () => {
      const mockContext = {
        switchToHttp: () => ({
          getRequest: () => ({
            headers: { "x-api-key": "wrong-api-key" },
          }),
        }),
      };

      expect(() => guard.canActivate(mockContext as never)).toThrow(UnauthorizedException);
      expect(() => guard.canActivate(mockContext as never)).toThrow("Invalid API key");
    });
  });
});
