const request = require('supertest');
const { app, calculateDestination } = require('../app/server');

// Mock pg Pool
jest.mock('pg', () => {
  const mPool = {
    query: jest.fn(),
    on: jest.fn(),
    end: jest.fn(),
  };
  return { Pool: jest.fn(() => mPool) };
});

const { Pool } = require('pg');
const pool = new Pool();

describe('Line of Sight Backend', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('calculateDestination', () => {
    test('should calculate correct destination for North (0 degrees)', () => {
      const start = { lat: 0, lon: 0 };
      const dest = calculateDestination(start.lat, start.lon, 0, 111.12); // ~1 degree North
      expect(dest.lat).toBeCloseTo(1, 1);
      expect(dest.lon).toBeCloseTo(0, 1);
    });

    test('should calculate correct destination for East (90 degrees)', () => {
      const start = { lat: 0, lon: 0 };
      const dest = calculateDestination(start.lat, start.lon, 90, 111.12); // ~1 degree East at equator
      expect(dest.lat).toBeCloseTo(0, 1);
      expect(dest.lon).toBeCloseTo(1, 1);
    });
  });

  describe('GET /api/health', () => {
    test('should return 200 OK', async () => {
      const response = await request(app).get('/api/health');
      expect(response.status).toBe(200);
      expect(response.body.status).toBe('ok');
    });
  });

  describe('GET /api/line-of-sight', () => {
    test('should return valid response structure', async () => {
      // Mock the water checks and the main city query
      pool.query
        .mockResolvedValueOnce({ rows: [{ has_land: true }] }) // Simplified for tests, it actually calls many times
        .mockResolvedValue({ rows: [{ id: 1, name: 'London', population: 9000000, country: 'GB', lat: 51.5, lon: -0.1, distance_off_line_km: 0, distance_from_start_km: 0, pos_on_line: 0 }] });

      const response = await request(app)
        .get('/api/line-of-sight')
        .query({ lat: 51.5, lon: -0.1, direction: 45, tolerance: 50 });

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.data.conurbations).toBeDefined();
      expect(response.body.data.line_coordinates).toBeDefined();
    });

    test('should handle database errors', async () => {
      pool.query.mockRejectedValue(new Error('DB Error'));

      const response = await request(app)
        .get('/api/line-of-sight')
        .query({ lat: 51.5, lon: -0.1, direction: 45, tolerance: 50 });

      expect(response.status).toBe(500);
      expect(response.body.success).toBe(false);
    });
  });
});
