import { provideHttpClient } from '@angular/common/http';
import {
  HttpTestingController,
  provideHttpClientTesting,
} from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { EbsApiService, EBS_BASE_URL } from './ebs-api.service';

const BASE = 'https://test.local';

describe('EbsApiService', () => {
  let service: EbsApiService;
  let controller: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        provideHttpClient(),
        provideHttpClientTesting(),
        { provide: EBS_BASE_URL, useValue: BASE },
      ],
    });
    service = TestBed.inject(EbsApiService);
    controller = TestBed.inject(HttpTestingController);
  });

  afterEach(() => controller.verify());

  describe('getMissionState', () => {
    it('GETs /missions/state and returns null for no active mission', () => {
      let result: unknown;
      service.getMissionState().subscribe((v) => (result = v));

      controller.expectOne(`${BASE}/missions/state`).flush(null);
      expect(result).toBeNull();
    });

    it('throws ZodError when server returns invalid shape', () => {
      let error: unknown;
      service.getMissionState().subscribe({ error: (e) => (error = e) });

      controller.expectOne(`${BASE}/missions/state`).flush({ bad: 'data' });
      expect(error).toBeDefined();
    });
  });

  describe('startMission', () => {
    it('POSTs to /missions/start with difficulty and durationMinutes', () => {
      service.startMission({ difficulty: 2, durationMinutes: 20 }).subscribe({ error: () => undefined });

      const req = controller.expectOne(`${BASE}/missions/start`);
      expect(req.request.method).toBe('POST');
      expect(req.request.body).toEqual({ difficulty: 2, durationMinutes: 20 });
      req.flush({ bad: 'shape' });
    });

    it('throws ZodError for invalid request before sending', () => {
      expect(() => service.startMission({ difficulty: 99, durationMinutes: 20 })).toThrow();
      controller.expectNone(`${BASE}/missions/start`);
    });
  });

  describe('choosePerk', () => {
    it('POSTs to /missions/choose-perk with perkKey', () => {
      service.choosePerk({ perkKey: 'iron_will' }).subscribe({ error: () => undefined });

      const req = controller.expectOne(`${BASE}/missions/choose-perk`);
      expect(req.request.method).toBe('POST');
      expect(req.request.body).toEqual({ perkKey: 'iron_will' });
      req.flush({ bad: 'shape' });
    });

    it('throws ZodError for empty perkKey before sending request', () => {
      expect(() => service.choosePerk({ perkKey: '' })).toThrow();
      controller.expectNone(`${BASE}/missions/choose-perk`);
    });
  });
});
