// Mock axios before importing services
jest.mock('axios', () => ({
  create: jest.fn(() => ({
    interceptors: {
      request: { use: jest.fn() },
      response: { use: jest.fn() }
    },
    get: jest.fn(),
    post: jest.fn(),
    put: jest.fn(),
    delete: jest.fn()
  }))
}));

import { filamentService, authService } from '../src/services/api';

describe('Filament CRUD Operations', () => {
  let authToken: string;

  beforeAll(async () => {
    // Mock successful login
    jest.spyOn(authService, 'login').mockResolvedValue({ token: 'test-token' });
    const loginResponse = await authService.login('admin', 'admin123');
    authToken = loginResponse.token;
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('Create Filament', () => {
    it('should create a new filament without brand field', async () => {
      const newFilament = {
        tip: 'PLA',
        finish: 'Basic',
        boja: 'Black',
        boja_hex: '#000000',
        refill: '2',
        spulna: '1 spulna',
        kolicina: '3',
        cena: '3999'
      };

      const mockResponse = {
        id: '123',
        ...newFilament,
        boja_hex: '#000000',
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString()
      };

      jest.spyOn(filamentService, 'create').mockResolvedValue(mockResponse);

      const result = await filamentService.create(newFilament);

      expect(result).toEqual(mockResponse);
      expect(filamentService.create).toHaveBeenCalledWith(newFilament);
      
      // Verify no brand field was sent
      const callArg = (filamentService.create as jest.Mock).mock.calls[0][0];
      expect(callArg).not.toHaveProperty('brand');
    });

    it('should use boja_hex field directly', async () => {
      const filamentWithHex = {
        tip: 'PETG',
        finish: 'Silk',
        boja: 'Red',
        boja_hex: '#FF0000',
        refill: 'Ne',
        spulna: 'Ne',
        kolicina: '1',
        cena: '4500'
      };

      // Spy on the actual implementation
      const createSpy = jest.spyOn(filamentService, 'create');
      
      // We can't test the actual transformation without a real axios call,
      // but we can verify the method is called correctly
      await expect(async () => {
        await filamentService.create(filamentWithHex);
      }).not.toThrow();

      expect(createSpy).toHaveBeenCalledWith(filamentWithHex);
    });
  });

  describe('Update Filament', () => {
    it('should update a filament without brand field', async () => {
      const filamentId = '123';
      const updateData = {
        tip: 'ABS',
        finish: 'Matte',
        boja: 'Blue',
        boja_hex: '#0000FF',
        refill: '1',
        spulna: '2 spulna',
        kolicina: '4',
        cena: '5000'
      };

      const mockResponse = {
        id: filamentId,
        ...updateData,
        boja_hex: '#0000FF',
        updated_at: new Date().toISOString()
      };

      jest.spyOn(filamentService, 'update').mockResolvedValue(mockResponse);

      const result = await filamentService.update(filamentId, updateData);

      expect(result).toEqual(mockResponse);
      expect(filamentService.update).toHaveBeenCalledWith(filamentId, updateData);
      
      // Verify no brand field was sent
      const callArgs = (filamentService.update as jest.Mock).mock.calls[0];
      expect(callArgs[1]).not.toHaveProperty('brand');
    });
  });

  describe('Delete Filament', () => {
    it('should delete a filament by ID', async () => {
      const filamentId = '123';
      const mockResponse = { success: true };

      jest.spyOn(filamentService, 'delete').mockResolvedValue(mockResponse);

      const result = await filamentService.delete(filamentId);

      expect(result).toEqual(mockResponse);
      expect(filamentService.delete).toHaveBeenCalledWith(filamentId);
    });
  });

  describe('Get All Filaments', () => {
    it('should retrieve all filaments with boja_hex field', async () => {
      const mockFilaments = [
        {
          id: '1',
          tip: 'PLA',
          finish: 'Basic',
          boja: 'Black',
          boja_hex: '#000000',
          refill: '2',
          spulna: '1 spulna',
          kolicina: '3',
          cena: '3999'
        },
        {
          id: '2',
          tip: 'PETG',
          finish: 'Silk',
          boja: 'Red',
          boja_hex: '#FF0000',
          refill: 'Ne',
          spulna: 'Ne',
          kolicina: '1',
          cena: '4500'
        }
      ];

      // No transformation needed anymore - we use boja_hex directly
      const expectedFilaments = mockFilaments;

      jest.spyOn(filamentService, 'getAll').mockResolvedValue(expectedFilaments);

      const result = await filamentService.getAll();

      expect(result).toEqual(expectedFilaments);
      expect(result[0]).toHaveProperty('boja_hex', '#000000');
      expect(result[1]).toHaveProperty('boja_hex', '#FF0000');
    });
  });

  describe('Quantity Calculations', () => {
    it('should correctly calculate total quantity from refill and spulna', () => {
      const testCases = [
        { refill: '2', spulna: '1 spulna', expected: 3 },
        { refill: 'Ne', spulna: '3 spulna', expected: 3 },
        { refill: '1', spulna: 'Ne', expected: 1 },
        { refill: 'Da', spulna: 'spulna', expected: 2 }
      ];

      testCases.forEach(({ refill, spulna, expected }) => {
        // Parse refill
        const refillCount = parseInt(refill) || (refill?.toLowerCase() === 'da' ? 1 : 0);
        
        // Parse spulna
        const vakuumMatch = spulna?.match(/^(\d+)\s*spulna/);
        const vakuumCount = vakuumMatch ? parseInt(vakuumMatch[1]) : (spulna?.toLowerCase().includes('spulna') ? 1 : 0);
        
        const total = refillCount + vakuumCount;
        
        expect(total).toBe(expected);
      });
    });
  });
});