// src/tests/integration/flyer.integration.test.ts
import { describe, it, expect, beforeAll } from 'vitest';
import * as apiClient from '../../services/apiClient';
import type { Flyer, FlyerItem } from '../../types';

/**
 * @vitest-environment node
 */

describe('Public Flyer API Routes Integration Tests', () => {
  let flyers: Flyer[] = [];

  // Fetch flyers once before all tests in this suite to use in subsequent tests.
  beforeAll(async () => {
    const response = await apiClient.fetchFlyers();
    flyers = await response.json();
  });

  describe('GET /api/flyers', () => {
    it('should return a list of flyers', async () => {
      // Act: Call the API endpoint using the client function.
      const response = await apiClient.fetchFlyers();
      const flyers: Flyer[] = await response.json();

      // Assert: Verify the response is successful and contains the expected data structure.
      expect(response.ok).toBe(true);
      expect(flyers).toBeInstanceOf(Array);

      // The seed script creates at least one flyer, so we expect the array not to be empty.
      expect(flyers.length).toBeGreaterThan(0);

      // Check the shape of the first flyer object to ensure it matches the expected type.
      const firstFlyer = flyers[0];
      expect(firstFlyer).toHaveProperty('flyer_id');
      expect(firstFlyer).toHaveProperty('file_name');
      expect(firstFlyer).toHaveProperty('image_url');
      expect(firstFlyer).toHaveProperty('store');
      expect(firstFlyer.store).toHaveProperty('store_id');
      expect(firstFlyer.store).toHaveProperty('name');
    });
  });

  describe('GET /api/flyers/:id/items', () => {
    it('should return items for a specific flyer', async () => {
      // Arrange: Ensure we have at least one flyer to test with.
      expect(flyers.length).toBeGreaterThan(0);
      const testFlyer = flyers[0];

      // Act: Fetch items for the first flyer.
      const response = await apiClient.fetchFlyerItems(testFlyer.flyer_id);
      const items: FlyerItem[] = await response.json();

      // Assert: Verify the response and data structure.
      expect(response.ok).toBe(true);
      expect(items).toBeInstanceOf(Array);

      // If there are items, check the shape of the first one.
      if (items.length > 0) {
        const firstItem = items[0];
        expect(firstItem).toHaveProperty('flyer_item_id');
        expect(firstItem).toHaveProperty('item');
        expect(firstItem).toHaveProperty('price_display');
        expect(firstItem.flyer_id).toBe(testFlyer.flyer_id);
      }
    });
  });

  describe('POST /api/flyer-items/batch-fetch', () => {
    it('should return items for multiple flyer IDs', async () => {
      // Arrange: Get IDs from the flyers fetched in beforeAll.
      const flyerIds = flyers.map(f => f.flyer_id);
      expect(flyerIds.length).toBeGreaterThan(0);

      // Act: Fetch items for all available flyers.
      const response = await apiClient.fetchFlyerItemsForFlyers(flyerIds);
      const items: FlyerItem[] = await response.json();

      // Assert
      expect(response.ok).toBe(true);
      expect(items).toBeInstanceOf(Array);
      // The total number of items should be greater than or equal to the number of flyers (assuming at least one item per flyer).
      if (items.length > 0) {
        expect(items[0]).toHaveProperty('flyer_item_id');
      }
    });
  });

  describe('POST /api/flyer-items/batch-count', () => {
    it('should return the total count of items for multiple flyer IDs', async () => {
      // Arrange
      const flyerIds = flyers.map(f => f.flyer_id);
      expect(flyerIds.length).toBeGreaterThan(0);

      // Act
      const response = await apiClient.countFlyerItemsForFlyers(flyerIds);
      const result = await response.json();

      // Assert
      expect(result.count).toBeTypeOf('number');
      expect(result.count).toBeGreaterThan(0);
    });
  });
});