import { describe, it, expect, beforeEach, vi } from 'vitest';
import { ItemsController } from './items.controller';
import { ItemsService } from './items.service';

describe('ItemsController - search endpoint', () => {
  let controller: ItemsController;
  let service: ItemsService;

  beforeEach(() => {
    // Mock the service
    service = {
      searchItems: vi.fn(),
    } as any;

    controller = new ItemsController(service);
  });

  describe('GET /items/search', () => {
    it('should call service.searchItems with query parameter', async () => {
      const mockResults = [
        {
          _id: '123',
          itemCode: 'RICE-001',
          itemName: 'Basmati Rice',
          description: 'Premium Basmati Rice',
          bagWeightKg: 25,
          unit: 'BAG/1x25kg',
        },
      ];

      vi.mocked(service.searchItems).mockResolvedValue(mockResults);

      const result = await controller.searchItems('rice');

      expect(service.searchItems).toHaveBeenCalledWith('rice');
      expect(result).toEqual(mockResults);
    });

    it('should handle empty query by passing empty string to service', async () => {
      vi.mocked(service.searchItems).mockResolvedValue([]);

      const result = await controller.searchItems('');

      expect(service.searchItems).toHaveBeenCalledWith('');
      expect(result).toEqual([]);
    });

    it('should handle undefined query by passing empty string to service', async () => {
      vi.mocked(service.searchItems).mockResolvedValue([]);

      const result = await controller.searchItems(undefined as any);

      expect(service.searchItems).toHaveBeenCalledWith('');
      expect(result).toEqual([]);
    });

    it('should return empty array for queries < 2 characters', async () => {
      vi.mocked(service.searchItems).mockResolvedValue([]);

      const result = await controller.searchItems('a');

      expect(service.searchItems).toHaveBeenCalledWith('a');
      expect(result).toEqual([]);
    });

    it('should handle special characters in query', async () => {
      vi.mocked(service.searchItems).mockResolvedValue([]);

      const result = await controller.searchItems('test*query');

      expect(service.searchItems).toHaveBeenCalledWith('test*query');
      expect(result).toEqual([]);
    });

    it('should return multiple matching items', async () => {
      const mockResults = [
        {
          _id: '123',
          itemCode: 'RICE-001',
          itemName: 'Basmati Rice',
          description: 'Premium Basmati Rice',
          bagWeightKg: 25,
          unit: 'BAG/1x25kg',
        },
        {
          _id: '124',
          itemCode: 'RICE-002',
          itemName: 'Jasmine Rice',
          description: 'Fragrant Jasmine Rice',
          bagWeightKg: 40,
          unit: 'BAG/1x40kg',
        },
      ];

      vi.mocked(service.searchItems).mockResolvedValue(mockResults);

      const result = await controller.searchItems('rice');

      expect(service.searchItems).toHaveBeenCalledWith('rice');
      expect(result).toHaveLength(2);
      expect(result).toEqual(mockResults);
    });

    it('should be case-insensitive', async () => {
      const mockResults = [
        {
          _id: '123',
          itemCode: 'RICE-001',
          itemName: 'Basmati Rice',
          description: 'Premium Basmati Rice',
          bagWeightKg: 25,
          unit: 'BAG/1x25kg',
        },
      ];

      vi.mocked(service.searchItems).mockResolvedValue(mockResults);

      const result1 = await controller.searchItems('RICE');
      const result2 = await controller.searchItems('rice');
      const result3 = await controller.searchItems('RiCe');

      expect(service.searchItems).toHaveBeenCalledWith('RICE');
      expect(service.searchItems).toHaveBeenCalledWith('rice');
      expect(service.searchItems).toHaveBeenCalledWith('RiCe');
      expect(result1).toEqual(mockResults);
      expect(result2).toEqual(mockResults);
      expect(result3).toEqual(mockResults);
    });

    it('should limit results to 10 items', async () => {
      const mockResults = Array.from({ length: 10 }, (_, i) => ({
        _id: `${i}`,
        itemCode: `ITEM-${i.toString().padStart(3, '0')}`,
        itemName: `Item ${i}`,
        description: `Description ${i}`,
        bagWeightKg: 25,
        unit: 'BAG/1x25kg',
      }));

      vi.mocked(service.searchItems).mockResolvedValue(mockResults);

      const result = await controller.searchItems('item');

      expect(service.searchItems).toHaveBeenCalledWith('item');
      expect(result).toHaveLength(10);
    });
  });
});
