import { TestBed } from '@angular/core/testing';
import { firstValueFrom } from 'rxjs';
import { MarketplaceRevisionLocalGateway } from './marketplace-revision-local.gateway';

describe('MarketplaceRevisionLocalGateway (§5 pipeline invariants)', () => {
  let gateway: MarketplaceRevisionLocalGateway;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    gateway = TestBed.inject(MarketplaceRevisionLocalGateway);
  });

  it('creates a draft', async () => {
    const revision = await firstValueFrom(gateway.createDraft('mkt_1'));

    expect(revision.status).toBe('draft');
    expect(revision.marketplaceId).toBe('mkt_1');
  });

  it('walks the full pipeline in order: draft -> preview -> published', async () => {
    const draft = await firstValueFrom(gateway.createDraft('mkt_1'));
    const previewed = await firstValueFrom(gateway.validate('mkt_1', draft.id));
    expect(previewed.status).toBe('preview');

    const published = await firstValueFrom(gateway.publish('mkt_1', previewed.id));
    expect(published.status).toBe('published');
  });

  it('rejects publishing a draft that skipped validation', async () => {
    const draft = await firstValueFrom(gateway.createDraft('mkt_1'));

    await expectAsync(
      firstValueFrom(gateway.publish('mkt_1', draft.id)),
    ).toBeRejectedWithError(/must be in preview to publish/);
  });

  it('rejects validating a revision that is not a draft', async () => {
    const draft = await firstValueFrom(gateway.createDraft('mkt_1'));
    await firstValueFrom(gateway.validate('mkt_1', draft.id));

    await expectAsync(
      firstValueFrom(gateway.validate('mkt_1', draft.id)),
    ).toBeRejectedWithError(/must be a draft to validate/);
  });

  it('rejects rolling back a revision that was never published', async () => {
    const draft = await firstValueFrom(gateway.createDraft('mkt_1'));

    await expectAsync(
      firstValueFrom(gateway.rollback('mkt_1', draft.id)),
    ).toBeRejectedWithError(/Only a published revision can be rolled back/);
  });

  it('rollback creates a new revision rather than mutating the published one', async () => {
    const draft = await firstValueFrom(gateway.createDraft('mkt_1'));
    const previewed = await firstValueFrom(gateway.validate('mkt_1', draft.id));
    const published = await firstValueFrom(gateway.publish('mkt_1', previewed.id));

    const rolledBack = await firstValueFrom(gateway.rollback('mkt_1', published.id));

    expect(rolledBack.id).not.toBe(published.id);
    expect(rolledBack.supersedesRevisionId).toBe(published.id);
    expect(rolledBack.status).toBe('published');
  });

  it('rejects an unknown revision id', async () => {
    await expectAsync(
      firstValueFrom(gateway.validate('mkt_1', 'nope')),
    ).toBeRejectedWithError(/Revision not found/);
  });
});
