// src/tests/integration/public.routes.integration.test.ts
import { describe, it, expect, beforeAll } from 'vitest';
import supertest from 'supertest';
import type { Flyer, FlyerItem, Recipe, RecipeComment, DietaryRestriction, Appliance } from '../../types';

const API_URL = process.env.VITE_API_BASE_URL || 'http://localhost:3001/api';
const request = supertest(API_URL.replace('/api', '')); // supertest needs the server's base URL

describe('Public API Routes Integration Tests', () => {
  // Shared state for tests
  let flyers: Flyer[] = [];
  let recipes: Recipe[] = [];

  beforeAll(async () => {
    // Pre-fetch some data to use in subsequent tests
    const flyersRes = await request.get('/api/flyers');
    flyers = flyersRes.body;

    // The seed script creates a recipe, let's find it to test comments
    const recipeRes = await request.get('/api/recipes/by-ingredient-and-tag?ingredient=Chicken&tag=Dinner');
    recipes = recipeRes.body;
  });

  describe('Health Check Endpoints', () => {
    it('GET /api/health/ping should return "pong"', async () => {
      const response = await request.get('/api/health/ping');
      expect(response.status).toBe(200);
      expect(response.text).toBe('pong');
    });

    it('GET /api/health/db-schema should return success', async () => {
      const response = await request.get('/api/health/db-schema');
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });

    it('GET /api/health/storage should return success', async () => {
      const response = await request.get('/api/health/storage');
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });

    it('GET /api/health/db-pool should return success', async () => {
      const response = await request.get('/api/health/db-pool');
      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
    });
  });

  describe('Public Data Endpoints', () => {
    it('GET /api/time should return the server time', async () => {
      const response = await request.get('/api/time');
      expect(response.status).toBe(200);
      expect(response.body).toHaveProperty('currentTime');
      expect(response.body).toHaveProperty('year');
      expect(response.body).toHaveProperty('week');
    });

    it('GET /api/flyers should return a list of flyers', async () => {
      expect(flyers.length).toBeGreaterThan(0);
      expect(flyers[0]).toHaveProperty('flyer_id');
      expect(flyers[0]).toHaveProperty('store');
    });

    it('GET /api/flyers/:id/items should return items for a specific flyer', async () => {
      const testFlyer = flyers[0];
      const response = await request.get(`/api/flyers/${testFlyer.flyer_id}/items`);
      const items: FlyerItem[] = response.body;
      expect(response.status).toBe(200);
      expect(items).toBeInstanceOf(Array);
      if (items.length > 0) {
        expect(items[0].flyer_id).toBe(testFlyer.flyer_id);
      }
    });

    it('POST /api/flyer-items/batch-fetch should return items for multiple flyers', async () => {
      const flyerIds = flyers.map(f => f.flyer_id);
      const response = await request.post('/api/flyer-items/batch-fetch').send({ flyerIds });
      const items: FlyerItem[] = response.body;
      expect(response.status).toBe(200);
      expect(items).toBeInstanceOf(Array);
      expect(items.length).toBeGreaterThan(0);
    });

    it('POST /api/flyer-items/batch-count should return a count for multiple flyers', async () => {
      const flyerIds = flyers.map(f => f.flyer_id);
      const response = await request.post('/api/flyer-items/batch-count').send({ flyerIds });
      expect(response.status).toBe(200);
      expect(response.body.count).toBeTypeOf('number');
      expect(response.body.count).toBeGreaterThan(0);
    });

    it('GET /api/master-items should return a list of master grocery items', async () => {
      const response = await request.get('/api/master-items');
      const masterItems = response.body;
      expect(response.status).toBe(200);
      expect(masterItems).toBeInstanceOf(Array);
      expect(masterItems.length).toBeGreaterThan(0);
      expect(masterItems[0]).toHaveProperty('master_grocery_item_id');
    });

    it('GET /api/recipes/by-sale-percentage should return recipes', async () => {
      const response = await request.get('/api/recipes/by-sale-percentage?minPercentage=10');
      const recipes: Recipe[] = response.body;
      expect(response.status).toBe(200);
      expect(recipes).toBeInstanceOf(Array);
    });

    it('GET /api/recipes/by-ingredient-and-tag should return recipes', async () => {
      const response = await request.get('/api/recipes/by-ingredient-and-tag?ingredient=Chicken&tag=Dinner');
      const recipes: Recipe[] = response.body;
      expect(response.status).toBe(200);
      expect(recipes).toBeInstanceOf(Array);
      expect(recipes.length).toBeGreaterThan(0); // Seed data includes this
    });

    it('GET /api/recipes/:recipeId/comments should return comments for a recipe', async () => {
      const testRecipe = recipes[0];
      expect(testRecipe).toBeDefined();
      const response = await request.get(`/api/recipes/${testRecipe.recipe_id}/comments`);
      const comments: RecipeComment[] = response.body;
      expect(response.status).toBe(200);
      expect(comments).toBeInstanceOf(Array);
    });

    it('GET /api/stats/most-frequent-sales should return frequent items', async () => {
      const response = await request.get('/api/stats/most-frequent-sales?days=365&limit=5');
      const items = response.body;
      expect(response.status).toBe(200);
      expect(items).toBeInstanceOf(Array);
    });

    it('GET /api/dietary-restrictions should return a list of restrictions', async () => {
      const response = await request.get('/api/dietary-restrictions');
      const restrictions: DietaryRestriction[] = response.body;
      expect(response.status).toBe(200);
      expect(restrictions).toBeInstanceOf(Array);
      expect(restrictions.length).toBeGreaterThan(0);
      expect(restrictions[0]).toHaveProperty('dietary_restriction_id');
    });

    it('GET /api/appliances should return a list of appliances', async () => {
      const response = await request.get('/api/appliances');
      const appliances: Appliance[] = response.body;
      expect(response.status).toBe(200);
      expect(appliances).toBeInstanceOf(Array);
      expect(appliances.length).toBeGreaterThan(0);
      expect(appliances[0]).toHaveProperty('appliance_id');
    });
  });
});