import axios from 'axios';
import {
  listLocations,
  getLocation,
  addLocation,
  updateLocation,
  deleteLocation
} from '../api/locations';

jest.mock('axios');

describe('Location API Functions', () => {
  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('listLocations', () => {
    test('should fetch all locations successfully', async () => {
      const mockLocations = [
        {
          "id": 1,
          "name": "Warszawa",
          "description": "Stolica Polski, położona w centralnej części kraju. Warszawa jest największym miastem w Polsce, znanym z bogatej historii, kultury i architektury. Warto zobaczyć Zamek Królewski, Stare Miasto oraz Muzeum Powstania Warszawskiego. Miasto oferuje wiele atrakcji turystycznych, w tym parki, muzea i teatry. Warszawa jest również ważnym ośrodkiem gospodarczym i kulturalnym.",
          "image": "https://www.niesamowitapolska.eu/images/mazowieckie/warszawa/38607734_m.jpg",
          "area": 517.21,
          "population": 1790658
        },
        {
          "id": 2,
          "name": "Kielce",
          "description": "Stolica województwa świętokrzyskiego, położona w centralnej Polsce. Kielce to miasto w centralnej Polsce, znane z pięknych krajobrazów i bogatej historii. Warto odwiedzić Kielecki Park Etnograficzny, Muzeum Zabawek oraz Katedrę Wniebowzięcia Najświętszej Maryi Panny. Kielce są również znane z licznych festiwali i wydarzeń kulturalnych. Miasto oferuje wiele atrakcji turystycznych, w tym parki, muzea i teatry.",
          "image": "https://as2.ftcdn.net/jpg/05/42/90/67/1000_F_542906717_cf5i6HeCJsPluuH5tqq5MbsSdfpopmtT.webp",
          "area": 109.2,
          "population": 196000
        }
      ];
      axios.get.mockResolvedValueOnce({ data: mockLocations });

      const result = await listLocations();

      expect(axios.get).toHaveBeenCalledWith('https://hopp.zikor.pl/locations/all');
      expect(result).toEqual(mockLocations);
    });

    test('should handle error when fetching locations fails', async () => {
      axios.get.mockRejectedValueOnce(new Error('Network error'));

      await expect(listLocations()).rejects.toThrow('Network error');
      expect(axios.get).toHaveBeenCalledWith('https://hopp.zikor.pl/locations/all');
    });
  })

  describe('getLocation', () => {
    test('should fetch a location by id successfully', async () => {
      const mockLocation = {
        "id": 1,
        "name": "Warszawa",
        "description": "Stolica Polski, położona w centralnej części kraju.",
        "image": "https://www.niesamowitapolska.eu/images/mazowieckie/warszawa/38607734_m.jpg",
        "area": 517.21,
        "population": 1790658
      };
      
      axios.get.mockResolvedValueOnce({ data: mockLocation });

      const result = await getLocation(1);

      expect(axios.get).toHaveBeenCalledWith('https://hopp.zikor.pl/locations/1');
      expect(result).toEqual(mockLocation);
    });

    test('should handle error when fetching a location fails', async () => {
      axios.get.mockRejectedValueOnce(new Error('Location not found'));

      await expect(getLocation(999)).rejects.toThrow('Location not found');
      expect(axios.get).toHaveBeenCalledWith('https://hopp.zikor.pl/locations/999');
    });
  });

  describe('addLocation', () => {
    test('should add a location successfully', async () => {
      const newLocation = {
        "name": "Gdańsk",
        "description": "Miasto portowe na północy Polski.",
        "image": "https://example.com/gdansk.jpg",
        "area": 262.0,
        "population": 470907
      };
      
      const responseLocation = {
        "id": 3,
        ...newLocation
      };
      
      axios.post.mockResolvedValueOnce({ data: responseLocation });

      const result = await addLocation(newLocation);

      expect(axios.post).toHaveBeenCalledWith(
        'https://hopp.zikor.pl/locations/add', 
        newLocation, 
        { headers: { "Content-Type": "application/json" } }
      );
      expect(result).toEqual(responseLocation);
    });
  });

  describe('updateLocation', () => {
    test('should update a location successfully', async () => {
      const locationId = 2;
      const updatedDetails = {
        "name": "Kielce",
        "description": "Updated description for Kielce",
        "population": 200000
      };
      
      const responseLocation = {
        "id": locationId,
        "name": "Kielce",
        "description": "Updated description for Kielce",
        "image": "https://as2.ftcdn.net/jpg/05/42/90/67/1000_F_542906717_cf5i6HeCJsPluuH5tqq5MbsSdfpopmtT.webp",
        "area": 109.2,
        "population": 200000
      };
      
      axios.put.mockResolvedValueOnce({ data: responseLocation });

      const result = await updateLocation(locationId, updatedDetails);

      expect(axios.put).toHaveBeenCalledWith(
        `https://hopp.zikor.pl/locations/${locationId}`, 
        updatedDetails, 
        { headers: { "Content-Type": "application/json" } }
      );
      expect(result).toEqual(responseLocation);
    });

    test('should handle error when updating a location fails', async () => {
      const locationId = 999;
      const updatedDetails = { population: 300000 };
      
      axios.put.mockRejectedValueOnce(new Error('Failed to add location'));

      await expect(updateLocation(locationId, updatedDetails)).rejects.toThrow('Failed to add location');
      expect(axios.put).toHaveBeenCalledWith(
        `https://hopp.zikor.pl/locations/${locationId}`, 
        updatedDetails, 
        { headers: { "Content-Type": "application/json" } }
      );
    });
  });

  describe('deleteLocation', () => {
    test('should delete a location successfully', async () => {
      const locationId = 2;
      const responseData = { success: true, message: "Location deleted successfully" };
      
      axios.delete.mockResolvedValueOnce({ data: responseData });

      const result = await deleteLocation(locationId);

      expect(axios.delete).toHaveBeenCalledWith(`https://hopp.zikor.pl/locations/${locationId}`);
      expect(result).toEqual(responseData);
    });

    test('should handle error when deleting a location fails', async () => {
      const locationId = 999;
      
      axios.delete.mockRejectedValueOnce(new Error('Failed to delete location'));

      await expect(deleteLocation(locationId)).rejects.toThrow('Failed to delete location');
      expect(axios.delete).toHaveBeenCalledWith(`https://hopp.zikor.pl/locations/${locationId}`);
    });
  });
})