import { Test } from '@nestjs/testing';
import { of } from 'rxjs';
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import { SdsClientService } from './sds-client.service';

describe('SdsClientService', () => {
  let service: SdsClientService;
  let http: { post: jest.Mock; get: jest.Mock };

  beforeEach(async () => {
    http = { post: jest.fn(), get: jest.fn() };
    const moduleRef = await Test.createTestingModule({
      providers: [
        SdsClientService,
        { provide: HttpService, useValue: http },
        { provide: ConfigService, useValue: { get: jest.fn(() => undefined) } },
      ],
    }).compile();
    service = moduleRef.get(SdsClientService);
  });

  describe('fetchCategoryTree', () => {
    it('throws when the upstream returns a degenerate small tree', async () => {
      http.post.mockReturnValue(of({ data: [{ id: 1, name: 'Only' }] }));
      await expect(service.fetchCategoryTree()).rejects.toThrow(/degenerate/i);
    });

    it('returns the tree when it is healthy', async () => {
      const tree = Array.from({ length: 20 }, (_, i) => ({ id: i + 1, name: `C${i}` }));
      http.post.mockReturnValue(of({ data: tree }));
      const result = await service.fetchCategoryTree();
      expect(result).toHaveLength(20);
    });
  });

  describe('fetchProductDetail', () => {
    it('requests /products/{goodId} and validates the returned id', async () => {
      http.get.mockReturnValue(of({ data: { id: 168746, sku: 'OZ10827003' } }));

      const result = await service.fetchProductDetail('168746');

      expect(result.sku).toBe('OZ10827003');
      expect(http.get).toHaveBeenCalledWith(
        'https://mapi.sdspod.com/products/168746',
        expect.objectContaining({ headers: expect.any(Object) }),
      );
    });

    it('rejects a mismatched product response', async () => {
      http.get.mockReturnValue(of({ data: { id: 1 } }));
      await expect(service.fetchProductDetail('168746')).rejects.toThrow(/id mismatch/i);
    });
  });
});
