/**
 * IRU marketplace HTTP wiring: validation, pricing JSON, public inquiry shape (service spies; no DB).
 */

import request from 'supertest';
import { createIruMarketplaceHttpTestApp } from '@/__tests__/utils/iru-marketplace-http-test-app';
import { marketplaceService } from '@/core/iru/marketplace.service';

process.env.IRU_MARKETPLACE_RATE_LIMIT_IN_TEST = '1';

const app = createIruMarketplaceHttpTestApp();
const BASE = '/api/v1/iru/marketplace';

const validInquiryBody = {
  offeringId: 'IRU-OFF-TEST',
  organizationName: 'Test Reserve',
  institutionalType: 'CentralBank',
  jurisdiction: 'US',
  contactEmail: 'ops@example.org',
  contactName: 'Test User',
};

describe('IRU marketplace HTTP', () => {
  let submitSpy: jest.SpyInstance;
  let publicStatusSpy: jest.SpyInstance;
  let pricingSpy: jest.SpyInstance;

  beforeAll(() => {
    submitSpy = jest.spyOn(marketplaceService, 'submitInquiry').mockResolvedValue({
      inquiryId: 'INQ-MOCK',
      status: 'submitted',
      message: 'ok',
    });
    publicStatusSpy = jest.spyOn(marketplaceService, 'getInquiryStatusPublic').mockResolvedValue({
      inquiryId: 'INQ-PUB',
      status: 'submitted',
      offering: { name: 'Tier 1', capacityTier: 1 },
      submittedAt: new Date('2026-01-01T00:00:00.000Z'),
      acknowledgedAt: null,
      reviewedAt: null,
      completedAt: null,
    });
    pricingSpy = jest.spyOn(marketplaceService, 'calculatePricing').mockResolvedValue({
      offeringId: 'IRU-OFF-TEST',
      capacityTier: 1,
      basePrice: 100,
      currency: 'USD',
      pricingModel: 'Fixed',
    });
  });

  afterAll(() => {
    submitSpy.mockRestore();
    publicStatusSpy.mockRestore();
    pricingSpy.mockRestore();
  });

  beforeEach(() => {
    submitSpy.mockClear();
    publicStatusSpy.mockClear();
    pricingSpy.mockClear();
  });

  it('POST /inquiries returns 201 and strips validation before service', async () => {
    const res = await request(app).post(`${BASE}/inquiries`).send(validInquiryBody);
    expect(res.status).toBe(201);
    expect(submitSpy).toHaveBeenCalledTimes(1);
    expect(submitSpy.mock.calls[0][0]).toMatchObject({
      offeringId: 'IRU-OFF-TEST',
      contactEmail: 'ops@example.org',
    });
  });

  it('POST /inquiries returns 400 when jurisdiction is not 2 letters', async () => {
    const res = await request(app)
      .post(`${BASE}/inquiries`)
      .send({ ...validInquiryBody, jurisdiction: 'USA' });
    expect(res.status).toBe(400);
    expect(submitSpy).not.toHaveBeenCalled();
  });

  it('GET /offerings/:id/pricing returns 400 for invalid usageProfile JSON', async () => {
    const res = await request(app)
      .get(`${BASE}/offerings/IRU-OFF-TEST/pricing`)
      .query({ usageProfile: 'not-json{' });
    expect(res.status).toBe(400);
    expect(res.body.error?.code).toBe('INVALID_JSON');
    expect(pricingSpy).not.toHaveBeenCalled();
  });

  it('GET /offerings/:id/pricing hits calculatePricing when JSON is valid', async () => {
    const res = await request(app)
      .get(`${BASE}/offerings/IRU-OFF-TEST/pricing`)
      .query({ usageProfile: JSON.stringify({ tier: 1 }) });
    expect(res.status).toBe(200);
    expect(pricingSpy).toHaveBeenCalledWith('IRU-OFF-TEST', { tier: 1 });
  });

  it('GET /inquiries/:inquiryId returns public shape via getInquiryStatusPublic', async () => {
    const res = await request(app).get(`${BASE}/inquiries/INQ-PUB`);
    expect(res.status).toBe(200);
    expect(publicStatusSpy).toHaveBeenCalledWith('INQ-PUB');
    expect(res.body.data).toMatchObject({
      inquiryId: 'INQ-PUB',
      offering: { name: 'Tier 1', capacityTier: 1 },
    });
    expect(res.body.data).not.toHaveProperty('organizationName');
    expect(res.body.data).not.toHaveProperty('notes');
  });
});
