/**
 * @ai-summary Tests for Community Stations API Client
 */

import axios from 'axios';
import { communityStationsApi } from '../../api/community-stations.api';
import { SubmitStationData, ReviewDecision } from '../../types/community-stations.types';

jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;

describe('Community Stations API Client', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('submitStation', () => {
    it('should submit a station successfully', async () => {
      const submitData: SubmitStationData = {
        name: 'Shell Downtown',
        address: '123 Main St',
        city: 'Denver',
        state: 'CO',
        zipCode: '80202',
        latitude: 39.7392,
        longitude: -104.9903,
        brand: 'Shell',
        has93Octane: true,
        has93OctaneEthanolFree: false,
        price93: 3.599,
        notes: 'Good quality',
      };

      const mockResponse = {
        data: {
          id: '1',
          ...submitData,
          status: 'pending',
          submittedBy: 'user@example.com',
          createdAt: new Date().toISOString(),
          updatedAt: new Date().toISOString(),
        },
      };

      mockedAxios.post.mockResolvedValueOnce(mockResponse);

      const result = await communityStationsApi.submitStation(submitData);

      expect(result).toEqual(mockResponse.data);
      expect(mockedAxios.post).toHaveBeenCalledWith(
        '/stations/community/submit',
        submitData
      );
    });

    it('should handle submission errors', async () => {
      const submitData: SubmitStationData = {
        name: 'Shell',
        address: '123 Main St',
        latitude: 39.7392,
        longitude: -104.9903,
        has93Octane: true,
        has93OctaneEthanolFree: false,
      };

      const mockError = new Error('Network error');
      mockedAxios.post.mockRejectedValueOnce(mockError);

      await expect(communityStationsApi.submitStation(submitData)).rejects.toThrow('Network error');
    });
  });

  describe('getMySubmissions', () => {
    it('should fetch user submissions', async () => {
      const mockSubmissions = [
        {
          id: '1',
          name: 'Shell Downtown',
          address: '123 Main St',
          latitude: 39.7392,
          longitude: -104.9903,
          has93Octane: true,
          has93OctaneEthanolFree: false,
          status: 'pending',
          submittedBy: 'user@example.com',
          createdAt: new Date().toISOString(),
          updatedAt: new Date().toISOString(),
        },
      ];

      mockedAxios.get.mockResolvedValueOnce({ data: mockSubmissions });

      const result = await communityStationsApi.getMySubmissions();

      expect(result).toEqual(mockSubmissions);
      expect(mockedAxios.get).toHaveBeenCalledWith('/stations/community/mine');
    });
  });

  describe('withdrawSubmission', () => {
    it('should withdraw a submission', async () => {
      mockedAxios.delete.mockResolvedValueOnce({ data: null });

      await communityStationsApi.withdrawSubmission('1');

      expect(mockedAxios.delete).toHaveBeenCalledWith('/stations/community/1');
    });
  });

  describe('getApprovedStations', () => {
    it('should fetch approved stations with pagination', async () => {
      const mockResponse = {
        data: {
          stations: [
            {
              id: '1',
              name: 'Shell Downtown',
              address: '123 Main St',
              latitude: 39.7392,
              longitude: -104.9903,
              has93Octane: true,
              has93OctaneEthanolFree: false,
              status: 'approved',
              submittedBy: 'user@example.com',
              createdAt: new Date().toISOString(),
              updatedAt: new Date().toISOString(),
            },
          ],
          total: 1,
          page: 0,
          limit: 50,
        },
      };

      mockedAxios.get.mockResolvedValueOnce(mockResponse);

      const result = await communityStationsApi.getApprovedStations(0, 50);

      expect(result).toEqual(mockResponse.data);
      expect(mockedAxios.get).toHaveBeenCalledWith('/stations/community/approved', {
        params: { page: 0, limit: 50 },
      });
    });
  });

  describe('reviewStation (admin)', () => {
    it('should approve a station', async () => {
      const decision: ReviewDecision = { status: 'approved' };

      const mockResponse = {
        data: {
          id: '1',
          status: 'approved',
          reviewedAt: new Date().toISOString(),
          reviewedBy: 'admin@example.com',
        },
      };

      mockedAxios.patch.mockResolvedValueOnce(mockResponse);

      const result = await communityStationsApi.reviewStation('1', decision);

      expect(result).toEqual(mockResponse.data);
      expect(mockedAxios.patch).toHaveBeenCalledWith(
        '/stations/community/admin/1/review',
        decision
      );
    });

    it('should reject a station with reason', async () => {
      const decision: ReviewDecision = {
        status: 'rejected',
        rejectionReason: 'Invalid location',
      };

      const mockResponse = {
        data: {
          id: '1',
          status: 'rejected',
          rejectionReason: 'Invalid location',
          reviewedAt: new Date().toISOString(),
          reviewedBy: 'admin@example.com',
        },
      };

      mockedAxios.patch.mockResolvedValueOnce(mockResponse);

      const result = await communityStationsApi.reviewStation('1', decision);

      expect(result).toEqual(mockResponse.data);
      expect(mockedAxios.patch).toHaveBeenCalledWith(
        '/stations/community/admin/1/review',
        decision
      );
    });
  });

  describe('bulkReviewStations (admin)', () => {
    it('should bulk approve stations', async () => {
      const ids = ['1', '2', '3'];
      const decision: ReviewDecision = { status: 'approved' };

      const mockResponse = {
        data: [
          { id: '1', status: 'approved' },
          { id: '2', status: 'approved' },
          { id: '3', status: 'approved' },
        ],
      };

      mockedAxios.post.mockResolvedValueOnce(mockResponse);

      const result = await communityStationsApi.bulkReviewStations(ids, decision);

      expect(result).toEqual(mockResponse.data);
      expect(mockedAxios.post).toHaveBeenCalledWith('/stations/community/admin/bulk-review', {
        ids,
        ...decision,
      });
    });
  });
});
