/**
 * @fileoverview Tests for compatibility layer functions
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';

// Mock loggers used by the modules
const mockCompatibilityLogger = {
  warn: vi.fn(),
  error: vi.fn(),
  info: vi.fn(),
  debug: vi.fn(),
};

const mockFactoryLogger = {
  warn: vi.fn(),
  error: vi.fn(),
  info: vi.fn(),
  debug: vi.fn(),
};

// Mock the logger module
vi.mock('../utils/logging/logger.js', () => ({
  createLogger: vi.fn((name: string) => {
    if (name === 'Compatibility') {
      return mockCompatibilityLogger;
    }
    return mockFactoryLogger;
  }),
}));

// Mock the ToolRegistry
const mockToolRegistry = {
  registerTool: vi.fn(),
  getToolNames: vi.fn(() => ['tool1', 'tool2']),
};

vi.mock('../server/tool-registry.js', () => ({
  ToolRegistry: vi.fn(() => mockToolRegistry),
}));

// Mock registerDeepSourceTools
vi.mock('../server/tool-registration.js', () => ({
  registerDeepSourceTools: vi.fn(),
}));

// Mock createDefaultHandlerDeps
vi.mock('../handlers/base/handler.factory.js', () => ({
  createDefaultHandlerDeps: vi.fn(() => ({
    getApiKey: vi.fn(() => 'test-api-key'),
    clientFactory: {},
    projectRepository: {},
    analysisRunRepository: {},
    metricsRepository: {},
    complianceReportRepository: {},
    logger: {
      warn: vi.fn(),
      error: vi.fn(),
      info: vi.fn(),
      debug: vi.fn(),
    },
  })),
}));

// Import after mocks are set up
import { validateEnvironment, createAndConfigureToolRegistry } from '../compatibility.js';
import { ToolRegistry } from '../server/tool-registry.js';
import { registerDeepSourceTools } from '../server/tool-registration.js';
import { createDefaultHandlerDeps } from '../handlers/base/handler.factory.js';

describe('Compatibility Layer', () => {
  let originalEnv: NodeJS.ProcessEnv;

  beforeEach(() => {
    originalEnv = { ...process.env };
    vi.clearAllMocks();
  });

  afterEach(() => {
    process.env = originalEnv;
    vi.restoreAllMocks();
  });

  describe('validateEnvironment', () => {
    it('should return true when DEEPSOURCE_API_KEY is set', () => {
      process.env.DEEPSOURCE_API_KEY = 'test-api-key-123';

      const result = validateEnvironment();

      expect(result).toBe(true);
      expect(mockCompatibilityLogger.warn).toHaveBeenCalledWith(
        expect.stringContaining('DEPRECATED: validateEnvironment() is deprecated')
      );
    });

    it('should return false when DEEPSOURCE_API_KEY is not set', () => {
      delete process.env.DEEPSOURCE_API_KEY;

      const result = validateEnvironment();

      expect(result).toBe(false);
      expect(mockCompatibilityLogger.error).toHaveBeenCalledWith(
        'DEEPSOURCE_API_KEY environment variable is not set or is empty'
      );
    });

    it('should return false when DEEPSOURCE_API_KEY is empty string', () => {
      process.env.DEEPSOURCE_API_KEY = '';

      const result = validateEnvironment();

      expect(result).toBe(false);
      expect(mockCompatibilityLogger.error).toHaveBeenCalledWith(
        'DEEPSOURCE_API_KEY environment variable is not set or is empty'
      );
    });

    it('should return false when DEEPSOURCE_API_KEY is whitespace only', () => {
      process.env.DEEPSOURCE_API_KEY = '   ';

      const result = validateEnvironment();

      expect(result).toBe(false);
      expect(mockCompatibilityLogger.error).toHaveBeenCalledWith(
        'DEEPSOURCE_API_KEY environment variable is not set or is empty'
      );
    });

    it('should log deprecation warning every time', () => {
      process.env.DEEPSOURCE_API_KEY = 'test-key';

      validateEnvironment();
      validateEnvironment();

      expect(mockCompatibilityLogger.warn).toHaveBeenCalledTimes(2);
      expect(mockCompatibilityLogger.warn).toHaveBeenCalledWith(
        expect.stringContaining('DEPRECATED')
      );
    });
  });

  describe('createAndConfigureToolRegistry', () => {
    it('should create a registry with provided server', () => {
      const mockServer = { registerTool: vi.fn() };

      const result = createAndConfigureToolRegistry(mockServer as any);

      expect(result).toBeDefined();
      expect(mockCompatibilityLogger.warn).toHaveBeenCalledWith(
        expect.stringContaining('DEPRECATED: createAndConfigureToolRegistry() is deprecated')
      );
    });

    it('should register DeepSource tools successfully', () => {
      const mockServer = { registerTool: vi.fn() };

      createAndConfigureToolRegistry(mockServer as any);

      expect(vi.mocked(registerDeepSourceTools)).toHaveBeenCalled();
      expect(mockCompatibilityLogger.info).toHaveBeenCalledWith(
        'Successfully registered DeepSource tools in compatibility mode'
      );
    });

    it('should handle errors during tool registration gracefully', () => {
      const mockServer = { registerTool: vi.fn() };
      vi.mocked(registerDeepSourceTools).mockImplementationOnce(() => {
        throw new Error('Registration failed');
      });

      const result = createAndConfigureToolRegistry(mockServer as any);

      expect(result).toBeDefined(); // Should still return registry
      expect(mockCompatibilityLogger.error).toHaveBeenCalledWith(
        'Failed to register tools:',
        expect.any(Error)
      );
    });

    it('should pass custom dependencies to ToolRegistry', () => {
      const mockServer = { registerTool: vi.fn() };
      const mockDeps = {
        getApiKey: vi.fn(),
        clientFactory: {},
        logger: mockFactoryLogger,
      };

      createAndConfigureToolRegistry(mockServer as any, mockDeps as any);

      expect(ToolRegistry).toHaveBeenCalledWith(mockServer, mockDeps);
    });

    it('should use default dependencies when not provided', () => {
      const mockServer = { registerTool: vi.fn() };

      createAndConfigureToolRegistry(mockServer as any);

      expect(vi.mocked(createDefaultHandlerDeps)).toHaveBeenCalled();
      expect(ToolRegistry).toHaveBeenCalledWith(
        mockServer,
        expect.objectContaining({
          getApiKey: expect.any(Function),
        })
      );
    });
  });

  describe('Integration scenarios', () => {
    it('should work with validateEnvironment and createAndConfigureToolRegistry together', () => {
      const mockServer = { registerTool: vi.fn() };
      process.env.DEEPSOURCE_API_KEY = 'test-key';

      const isValid = validateEnvironment();
      expect(isValid).toBe(true);

      if (isValid) {
        const registry = createAndConfigureToolRegistry(mockServer as any);
        expect(registry).toBeDefined();
        expect(mockToolRegistry.getToolNames()).toEqual(['tool1', 'tool2']);
      }
    });

    it('should handle migration from old to new pattern', () => {
      const mockServer = { registerTool: vi.fn() };

      // Old pattern
      process.env.DEEPSOURCE_API_KEY = 'test-key';
      const isValid = validateEnvironment();

      if (isValid) {
        const registry = createAndConfigureToolRegistry(mockServer as any);

        // Should log deprecation warnings
        expect(mockCompatibilityLogger.warn).toHaveBeenCalledWith(
          expect.stringContaining('DEPRECATED')
        );

        // But should still work
        expect(registry).toBeDefined();
      }
    });
  });
});
