import { TestBed } from '@angular/core/testing';
import { describe, it, expect } from 'vitest';
import { Result } from '@shared/kernel/fp';
import { Brief, BriefDecisions } from '@brief/domain/brief';
import { BriefAdapter, BriefView } from '@brief/infrastructure/brief.adapter';
import { BriefStore } from './brief.store';

const decisions: BriefDecisions = {
  canEdit: true,
  canApprove: true,
  canReject: true,
  canSend: true,
};

const brief: Brief = {
  briefId: 'b1',
  beroep: 'arts',
  templateId: 't1',
  placeholders: [],
  sections: [],
  status: { tag: 'draft' },
  drafterId: 'u1',
};

const view: BriefView = { brief, availablePassages: [], decisions };

function setup(adapter: Partial<BriefAdapter>): BriefStore {
  TestBed.configureTestingModule({ providers: [{ provide: BriefAdapter, useValue: adapter }] });
  return TestBed.inject(BriefStore);
}

describe('BriefStore action state (Idle | Busy | Failed)', () => {
  it('is Busy synchronously once a transition starts, then Idle on success', async () => {
    const approved: BriefView = {
      ...view,
      brief: { ...brief, status: { tag: 'approved', approvedBy: 'u2', approvedAt: 't' } },
    };
    const store = setup({
      load: (): Promise<Result<string, BriefView>> => Promise.resolve({ ok: true, value: view }),
      save: (): Promise<Result<string, BriefView>> => Promise.resolve({ ok: true, value: view }),
      approve: (): Promise<Result<string, BriefView>> =>
        Promise.resolve({ ok: true, value: approved }),
    });
    await store.load();

    const pending = store.approve();
    expect(store.busy()).toBe(true); // set synchronously, before any await resolves

    await pending;
    expect(store.busy()).toBe(false);
    expect(store.lastError()).toBeNull();
  });

  it('goes Busy then Failed on a failing transition, surfacing the error', async () => {
    const store = setup({
      load: (): Promise<Result<string, BriefView>> => Promise.resolve({ ok: true, value: view }),
      save: (): Promise<Result<string, BriefView>> => Promise.resolve({ ok: true, value: view }),
      approve: (): Promise<Result<string, BriefView>> =>
        Promise.resolve({ ok: false, error: 'niet toegestaan' }),
    });
    await store.load();

    await store.approve();
    expect(store.busy()).toBe(false);
    expect(store.lastError()).toBe('niet toegestaan');
  });

  it('a subsequent successful transition clears a prior Failed state', async () => {
    let approveResult: Result<string, BriefView> = { ok: false, error: 'eerste poging mislukt' };
    const store = setup({
      load: (): Promise<Result<string, BriefView>> => Promise.resolve({ ok: true, value: view }),
      save: (): Promise<Result<string, BriefView>> => Promise.resolve({ ok: true, value: view }),
      approve: (): Promise<Result<string, BriefView>> => Promise.resolve(approveResult),
    });
    await store.load();

    await store.approve();
    expect(store.lastError()).toBe('eerste poging mislukt');

    approveResult = {
      ok: true,
      value: {
        ...view,
        brief: { ...brief, status: { tag: 'approved', approvedBy: 'u2', approvedAt: 't' } },
      },
    };
    await store.approve();
    expect(store.busy()).toBe(false);
    expect(store.lastError()).toBeNull();
  });
});
