import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { ReturnSearchResultItemComponent } from './return-search-result-item.component';
import { ReceiptListItem } from '@isa/oms/data-access';
import { formatName } from '@isa/utils/format-name';

jest.mock('@isa/utils/format-name', () => ({
  formatName: jest.fn(() => 'Formatted Name'),
}));

describe('ReturnSearchResultItemComponent', () => {
  let spectator: Spectator<ReturnSearchResultItemComponent>;
  const createComponent = createComponentFactory(
    ReturnSearchResultItemComponent,
  );

  const baseItem: ReceiptListItem = {
    billing: {
      person: { firstName: 'John', lastName: 'Doe' },
      organisation: { name: 'Acme Corp' },
      address: { zipCode: '12345', city: 'Metropolis' },
      communicationDetails: { email: 'john.doe@example.com' },
    },
    shipping: {
      address: { zipCode: '54321', city: 'Gotham' },
    },
    printedDate: '2024-06-01T12:00:00Z',
    receiptNumber: 'R-123',
    orderNumber: 'O-456',
  } as ReceiptListItem;

  it('should create', () => {
    spectator = createComponent({ props: { item: baseItem } });
    expect(spectator.component).toBeTruthy();
  });

  it('should compute name using formatName util', () => {
    spectator = createComponent({ props: { item: baseItem } });

    expect(formatName).toHaveBeenCalledWith({
      firstName: 'John',
      lastName: 'Doe',
      organisationName: 'Acme Corp',
    });
    expect(spectator.component.name()).toBe('Formatted Name');
  });

  it('should return receiptDate from item', () => {
    spectator = createComponent({ props: { item: baseItem } });

    expect(spectator.component.receiptDate()).toBe('2024-06-01T12:00:00Z');
  });

  it('should return receiptNumber from item', () => {
    spectator = createComponent({ props: { item: baseItem } });

    expect(spectator.component.receiptNumber()).toBe('R-123');
  });

  it('should return orderNumber from item', () => {
    spectator = createComponent({ props: { item: baseItem } });

    expect(spectator.component.orderNumber()).toBe('O-456');
  });

  it('should return email from billing communicationDetails', () => {
    spectator = createComponent({ props: { item: baseItem } });

    expect(spectator.component.email()).toBe('john.doe@example.com');
  });

  it('should return address from billing address if present', () => {
    spectator = createComponent({ props: { item: baseItem } });

    expect(spectator.component.address()).toBe('12345 Metropolis');
  });

  it('should return address from shipping address if billing address is missing', () => {
    const item = {
      ...baseItem,
      billing: { ...baseItem.billing, address: undefined },
    } as ReceiptListItem;
    spectator = createComponent({ props: { item } });

    expect(spectator.component.address()).toBe('54321 Gotham');
  });

  it('should return empty string if neither billing nor shipping address is present', () => {
    const item = {
      ...baseItem,
      billing: { ...baseItem.billing, address: undefined },
      shipping: { address: undefined },
    } as ReceiptListItem;
    spectator = createComponent({ props: { item } });

    expect(spectator.component.address()).toBe('');
  });

  it('should handle missing billing, shipping, and communicationDetails gracefully', () => {
    const item = {} as ReceiptListItem;
    spectator = createComponent({ props: { item } });

    expect(spectator.component.name()).toBe('Formatted Name');
    expect(spectator.component.receiptDate()).toBeUndefined();
    expect(spectator.component.receiptNumber()).toBeUndefined();
    expect(spectator.component.orderNumber()).toBeUndefined();
    expect(spectator.component.email()).toBeUndefined();
    expect(spectator.component.address()).toBe('');
  });

  it('should throw if item input is not set', () => {
    // Arrange & Act & Assert
    expect(() => createComponent()).toThrow();
  });
});
