import { describe, expect, it } from 'vitest';
import { OrderStateTransitionError } from '../domain/errors.js';
import { ALLOWED_TRANSITIONS, isTransitionAllowed, type OrderState } from '../domain/order.js';

describe('Order state machine', () => {
  it('allows the full happy-path transitions', () => {
    const path: OrderState[] = [
      'PENDING',
      'AWAITING_PAYMENT',
      'PAID',
      'PROCESSING',
      'SHIPPED',
      'DELIVERED',
    ];
    for (let i = 0; i < path.length - 1; i++) {
      expect(isTransitionAllowed(path[i] as OrderState, path[i + 1] as OrderState)).toBe(true);
    }
  });

  it('rejects SHIPPED back to PENDING (too far)', () => {
    expect(isTransitionAllowed('SHIPPED', 'PENDING')).toBe(false);
    expect(() => {
      if (!isTransitionAllowed('SHIPPED', 'PENDING'))
        throw new OrderStateTransitionError('SHIPPED', 'PENDING');
    }).toThrow(OrderStateTransitionError);
  });

  it('allows one-step backward transitions (F-125)', () => {
    expect(isTransitionAllowed('PROCESSING', 'PAID')).toBe(true);
    expect(isTransitionAllowed('SHIPPED', 'PROCESSING')).toBe(true);
    expect(isTransitionAllowed('DELIVERED', 'SHIPPED')).toBe(true);
  });

  it('keeps REFUNDED and PARTIALLY_REFUNDED terminal', () => {
    expect(ALLOWED_TRANSITIONS.REFUNDED).toEqual([]);
    expect(ALLOWED_TRANSITIONS.PARTIALLY_REFUNDED).toEqual([]);
    expect(isTransitionAllowed('REFUNDED', 'PAID')).toBe(false);
    expect(isTransitionAllowed('PARTIALLY_REFUNDED', 'PENDING')).toBe(false);
  });

  it('rejects illegal jumps', () => {
    expect(isTransitionAllowed('PENDING', 'SHIPPED')).toBe(false);
    expect(isTransitionAllowed('PAID', 'PENDING')).toBe(false);
  });
});
