/// <reference types="jest" />

/**
 * @jest-environment node
 */

// This test is skipped due to axios mocking challenges
// We cover the schema transformations in the zod-transforms.test.ts and schema-transformation-mocks.test.ts files instead

import { describe, it, expect, jest, beforeEach, afterEach, beforeAll } from '@jest/globals';

// Save original environment
const originalEnv = process.env;

// Set up environment variables
process.env.SONARQUBE_TOKEN = 'test-token';
process.env.SONARQUBE_URL = 'http://localhost:9000';
process.env.SONARQUBE_ORGANIZATION = 'test-org';

// Import the handlers
import {
  metricsHandler,
  issuesHandler,
  componentMeasuresHandler,
  componentsMeasuresHandler,
  measuresHistoryHandler,
  projectsHandler,
  healthHandler,
  statusHandler,
  pingHandler,
} from '../index.js';

// Import SonarQubeClient for mocking
import { SonarQubeClient } from '../sonarqube.js';

// Create mock implementation
jest.mock('../sonarqube.js', () => {
  const mockedClient = {
    listProjects: jest.fn().mockResolvedValue({
      projects: [{ key: 'test-project', name: 'Test Project' }],
      paging: { pageIndex: 1, pageSize: 10, total: 1 },
    }),
    getIssues: jest.fn().mockResolvedValue({
      issues: [{ key: 'test-issue', rule: 'test-rule', severity: 'MAJOR' }],
      components: [],
      rules: [],
      users: [],
      facets: [],
      paging: { pageIndex: 1, pageSize: 10, total: 1 },
    }),
    getMetrics: jest.fn().mockResolvedValue({
      metrics: [{ key: 'test-metric', name: 'Test Metric' }],
      paging: { pageIndex: 1, pageSize: 10, total: 1 },
    }),
    getHealth: jest.fn().mockResolvedValue({ health: 'GREEN', causes: [] }),
    getStatus: jest.fn().mockResolvedValue({ id: 'test-id', version: '1.0.0', status: 'UP' }),
    ping: jest.fn().mockResolvedValue('pong'),
    getComponentMeasures: jest.fn().mockResolvedValue({
      component: { key: 'test-component', measures: [{ metric: 'coverage', value: '85.4' }] },
      metrics: [{ key: 'coverage', name: 'Coverage' }],
    }),
    getComponentsMeasures: jest.fn().mockResolvedValue({
      components: [{ key: 'test-component', measures: [{ metric: 'coverage', value: '85.4' }] }],
      metrics: [{ key: 'coverage', name: 'Coverage' }],
      paging: { pageIndex: 1, pageSize: 10, total: 1 },
    }),
    getMeasuresHistory: jest.fn().mockResolvedValue({
      measures: [{ metric: 'coverage', history: [{ date: '2023-01-01', value: '85.4' }] }],
      paging: { pageIndex: 1, pageSize: 10, total: 1 },
    }),
  };

  return {
    SonarQubeClient: jest.fn(() => mockedClient),
  };
});

// Mock MCP Server
jest.mock('@modelcontextprotocol/sdk/server/mcp.js', () => {
  return {
    McpServer: jest.fn().mockImplementation(() => ({
      name: 'sonarqube-mcp-server',
      version: '1.1.0',
      tool: jest.fn(),
      connect: jest.fn(),
      server: { use: jest.fn() },
    })),
  };
});

jest.mock('@modelcontextprotocol/sdk/server/stdio.js', () => {
  return {
    StdioServerTransport: jest.fn().mockImplementation(() => ({
      connect: jest.fn().mockResolvedValue(undefined),
    })),
  };
});

describe('Lambda Handler Functions', () => {
  // Get reference to mocked client
  let mockClient;

  beforeAll(() => {
    // Get the mocked client from the SonarQubeClient constructor
    mockClient = new SonarQubeClient('', '', '');
  });

  beforeEach(() => {
    jest.resetModules();
    process.env = { ...originalEnv };
    process.env.SONARQUBE_TOKEN = 'test-token';
    process.env.SONARQUBE_URL = 'http://localhost:9000';
    process.env.SONARQUBE_ORGANIZATION = 'test-org';
  });

  afterEach(() => {
    process.env = originalEnv;
    jest.clearAllMocks();
  });

  describe('metricsHandler', () => {
    it('should transform parameters and call handleSonarQubeGetMetrics', async () => {
      const result = await metricsHandler({ page: '2', page_size: '20' });
      
      expect(mockClient.getMetrics).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });

    it('should handle null parameters', async () => {
      const result = await metricsHandler({ page: null, page_size: null });
      
      expect(mockClient.getMetrics).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
    });
  });

  describe('issuesHandler', () => {
    it('should map parameters and call handleSonarQubeGetIssues', async () => {
      const params = {
        project_key: 'test-project',
        severity: 'MAJOR',
        page: '2',
        page_size: '20',
        statuses: ['OPEN', 'CONFIRMED'],
        resolved: 'true',
      };
      
      const result = await issuesHandler(params);
      
      expect(mockClient.getIssues).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });

    it('should handle null parameters', async () => {
      const params = {
        project_key: 'test-project',
        severity: null,
        statuses: null,
      };
      
      const result = await issuesHandler(params);
      expect(mockClient.getIssues).toHaveBeenCalled();
      expect(result).toBeDefined();
    });
  });

  describe('componentMeasuresHandler', () => {
    it('should transform parameters and call handleSonarQubeComponentMeasures with a string metric key', async () => {
      const params = {
        component: 'test-component',
        metric_keys: 'coverage',
        branch: 'main',
      };
      
      const result = await componentMeasuresHandler(params);
      
      expect(mockClient.getComponentMeasures).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });

    it('should handle array metric keys', async () => {
      const params = {
        component: 'test-component',
        metric_keys: ['coverage', 'bugs'],
        additional_fields: ['periods'],
        pull_request: 'pr-123',
        period: '1',
      };
      
      const result = await componentMeasuresHandler(params);
      expect(mockClient.getComponentMeasures).toHaveBeenCalled();
      expect(result).toBeDefined();
    });
  });

  describe('componentsMeasuresHandler', () => {
    it('should transform parameters and call handleSonarQubeComponentsMeasures with string parameters', async () => {
      const params = {
        component_keys: 'test-component',
        metric_keys: 'coverage',
        page: '1',
        page_size: '10',
      };
      
      const result = await componentsMeasuresHandler(params);
      
      expect(mockClient.getComponentsMeasures).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });

    it('should handle array parameters', async () => {
      const params = {
        component_keys: ['comp1', 'comp2'],
        metric_keys: ['coverage', 'bugs'],
        additional_fields: ['periods'],
        branch: 'main',
        pull_request: 'pr-123',
        period: '1',
        page: '2',
        page_size: '20',
      };
      
      const result = await componentsMeasuresHandler(params);
      expect(mockClient.getComponentsMeasures).toHaveBeenCalled();
      expect(result).toBeDefined();
    });

    it('should handle null pagination parameters', async () => {
      const params = {
        component_keys: ['test-component'],
        metric_keys: ['coverage'],
        page: null,
        page_size: null,
      };
      
      const result = await componentsMeasuresHandler(params);
      expect(mockClient.getComponentsMeasures).toHaveBeenCalled();
      expect(result).toBeDefined();
    });
  });

  describe('measuresHistoryHandler', () => {
    it('should transform parameters and call handleSonarQubeMeasuresHistory with string parameters', async () => {
      const params = {
        component: 'test-component',
        metrics: 'coverage',
        from: '2023-01-01',
        to: '2023-12-31',
      };
      
      const result = await measuresHistoryHandler(params);
      
      expect(mockClient.getMeasuresHistory).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });

    it('should handle array parameters', async () => {
      const params = {
        component: 'test-component',
        metrics: ['coverage', 'bugs'],
        branch: 'main',
        pull_request: 'pr-123',
        page: '2',
        page_size: '20',
      };
      
      const result = await measuresHistoryHandler(params);
      expect(mockClient.getMeasuresHistory).toHaveBeenCalled();
      expect(result).toBeDefined();
    });

    it('should handle null pagination parameters', async () => {
      const params = {
        component: 'test-component',
        metrics: ['coverage'],
        page: null,
        page_size: null,
      };
      
      const result = await measuresHistoryHandler(params);
      expect(mockClient.getMeasuresHistory).toHaveBeenCalled();
      expect(result).toBeDefined();
    });
  });

  // Test the direct handler exports
  describe('Direct handler exports', () => {
    it('should expose projectsHandler that calls handleSonarQubeProjects', async () => {
      const result = await projectsHandler({ page: '1', page_size: '10' });
      
      expect(mockClient.listProjects).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });

    it('should expose healthHandler that calls handleSonarQubeGetHealth', async () => {
      const result = await healthHandler();
      
      expect(mockClient.getHealth).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });

    it('should expose statusHandler that calls handleSonarQubeGetStatus', async () => {
      const result = await statusHandler();
      
      expect(mockClient.getStatus).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });

    it('should expose pingHandler that calls handleSonarQubePing', async () => {
      const result = await pingHandler();
      
      expect(mockClient.ping).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(result.content).toBeDefined();
      expect(result.content[0].type).toBe('text');
    });
  });
});