/**
 * EN: Pact consumer test — Order Service consuming Catalog Service.
 * VI: Pact consumer test — Order Service sử dụng Catalog Service.
 *
 * Boundary: order -> catalog
 * Contract: Order Service calls GET /api/v1/products/{productId} to validate product.
 */
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { PactV3, MatchersV3 } from '@pact-foundation/pact';
import path from 'path';
import { fileURLToPath } from 'url';

const { like, eachLike, string, uuid, decimal, boolean } = MatchersV3;

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PACT_DIR = path.resolve(__dirname, '../../pacts');

// ---------------------------------------------------------------------------
// Pact provider definition
// ---------------------------------------------------------------------------
const provider = new PactV3({
  consumer: 'OrderService',
  provider: 'CatalogService',
  dir: PACT_DIR,
  logLevel: 'warn',
});

// ---------------------------------------------------------------------------
// Consumer-side HTTP client (mirrors OrderService.API CatalogServiceClient)
// ---------------------------------------------------------------------------
async function getProductById(baseUrl: string, productId: string) {
  const res = await fetch(`${baseUrl}/api/v1/products/${productId}`);
  if (!res.ok) return null;
  return res.json();
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
describe('OrderService → CatalogService contract', () => {
  const PRODUCT_ID = '550e8400-e29b-41d4-a716-446655440001';

  describe('GET /api/v1/products/{productId}', () => {
    it('returns product details when product exists', async () => {
      await provider
        .addInteraction({
          states: [{ description: 'product 550e8400-e29b-41d4-a716-446655440001 exists' }],
          uponReceiving: 'a request for product by ID',
          withRequest: {
            method: 'GET',
            path: `/api/v1/products/${PRODUCT_ID}`,
          },
          willRespondWith: {
            status: 200,
            headers: { 'Content-Type': 'application/json' },
            body: {
              // EN: Match the response shape — not exact values
              // VI: Khớp hình dạng response — không phải giá trị chính xác
              id: uuid(PRODUCT_ID),
              name: string('Espresso'),
              type: string('beverage'),
              price: decimal(35000),
              isActive: boolean(true),
            },
          },
        })
        .executeTest(async (mockServer) => {
          const product = await getProductById(mockServer.url, PRODUCT_ID);
          expect(product).not.toBeNull();
          expect(product.id).toBe(PRODUCT_ID);
          expect(product.isActive).toBe(true);
          expect(typeof product.price).toBe('number');
        });
    });

    it('returns null (404) when product does not exist', async () => {
      const MISSING_ID = '550e8400-e29b-41d4-a716-000000000000';
      await provider
        .addInteraction({
          states: [{ description: `product ${MISSING_ID} does not exist` }],
          uponReceiving: 'a request for a non-existent product',
          withRequest: {
            method: 'GET',
            path: `/api/v1/products/${MISSING_ID}`,
          },
          willRespondWith: {
            status: 404,
            headers: { 'Content-Type': 'application/json' },
            body: {
              success: boolean(false),
              error: like({ code: string('PRODUCT_NOT_FOUND') }),
            },
          },
        })
        .executeTest(async (mockServer) => {
          const product = await getProductById(mockServer.url, MISSING_ID);
          expect(product).toBeNull();
        });
    });
  });
});
