import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { vi, describe, test, expect, beforeEach } from 'vitest';
import App from '../App';
import apiService from '../services/api';

// Mock MapLibre GL
vi.mock('maplibre-gl', () => {
  const mInstance = {
    on: vi.fn(),
    off: vi.fn(),
    remove: vi.fn(),
    addSource: vi.fn(),
    removeSource: vi.fn(),
    addLayer: vi.fn(),
    removeLayer: vi.fn(),
    getSource: vi.fn(() => ({ setData: vi.fn() })),
    getLayer: vi.fn(),
    setLayoutProperty: vi.fn(),
    setStyle: vi.fn(),
    flyTo: vi.fn(),
    jumpTo: vi.fn(),
    fitBounds: vi.fn(),
    isStyleLoaded: vi.fn(() => true),
    setSky: vi.fn(),
    setTerrain: vi.fn(),
    setProjection: vi.fn(),
    hasImage: vi.fn(() => false),
    addImage: vi.fn(),
  };
  
  return {
    default: {
      Map: vi.fn(() => mInstance),
      Marker: vi.fn(() => ({
        setLngLat: vi.fn().mockReturnThis(),
        addTo: vi.fn().mockReturnThis(),
        remove: vi.fn().mockReturnThis(),
        getElement: vi.fn(() => {
          const el = document.createElement('div');
          // Add a simple way to trigger click for tests if needed
          return el;
        }),
      })),
      Popup: vi.fn(() => ({
        setLngLat: vi.fn().mockReturnThis(),
        setDOMContent: vi.fn().mockReturnThis(),
        addTo: vi.fn().mockReturnThis(),
        remove: vi.fn().mockReturnThis(),
        on: vi.fn().mockReturnThis(),
      })),
      LngLatBounds: vi.fn(() => ({
        extend: vi.fn().mockReturnThis(),
      })),
      MercatorCoordinate: {
        fromLngLat: vi.fn(() => ({ x: 0, y: 0, z: 0 })),
      }
    }
  };
});

// Mock apiService
vi.mock('../services/api', () => ({
  default: {
    getLineOfSight: vi.fn(),
    healthCheck: vi.fn(),
  }
}));

describe('App Component', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  test('renders the application title', () => {
    render(<App />);
    expect(screen.getByText(/Line of Sight Settings/i)).toBeInTheDocument();
  });

  test('renders initial controls', () => {
    render(<App />);
    // Use role or more specific text to avoid duplicates
    expect(screen.getByText(/Direction \(0-360°\):/i)).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /Show Line of Sight/i })).toBeInTheDocument();
  });

  test('calls API when clicking "Show Line of Sight"', async () => {
    apiService.getLineOfSight.mockResolvedValue({
      data: {
        success: true,
        data: {
          conurbations: [],
          line_coordinates: [{ lat: 0, lon: 0 }]
        }
      }
    });

    render(<App />);
    const button = screen.getByRole('button', { name: /Show Line of Sight/i });
    fireEvent.click(button);

    await waitFor(() => {
      expect(apiService.getLineOfSight).toHaveBeenCalled();
    });
  });

  test('toggles map style', () => {
    render(<App />);
    const darkButton = screen.getByRole('button', { name: /Dark/i });
    fireEvent.click(darkButton);
    expect(darkButton).toHaveClass('active-style');
  });
});
