import { createComponentFactory, Spectator } from '@ngneat/spectator';
import { SharedHistoryLogEntryComponent, SharedHistoryLogEntryValuesComponent } from '@shared/components/history';
import { DiffDTO, HistoryDTO as CrmHistoryDTO, HistoryDTO } from '@generated/swagger/crm-api';
import { HistoryDTO as OmsHistoryDTO } from '@generated/swagger/oms-api';
import { DatePipe } from '@angular/common';
import { registerLocaleData } from '@angular/common';
import localeDe from '@angular/common/locales/de';
import localeDeExtra from '@angular/common/locales/extra/de';
import { LOCALE_ID } from '@angular/core';

registerLocaleData(localeDe, 'de-DE', localeDeExtra);

describe('SharedHistoryLogEntryComponent', () => {
  let spectator: Spectator<SharedHistoryLogEntryComponent>;
  let historyMock: CrmHistoryDTO | OmsHistoryDTO;
  const datePipe = new DatePipe('de-DE');

  const createComponent = createComponentFactory({
    component: SharedHistoryLogEntryComponent,
    imports: [],
    declarations: [SharedHistoryLogEntryValuesComponent],
    providers: [{ provide: LOCALE_ID, useValue: 'de-DE' }],
  });

  beforeEach(() => {
    spectator = createComponent();
  });

  it('should create', () => {
    expect(spectator.component).toBeTruthy();
  });

  describe('log-entry', () => {
    beforeEach(() => {
      historyMock = {};
    });

    describe('type changed', () => {
      beforeEach(() => {
        historyMock = {
          changed: '2022-11-16T14:49:35.6895',
          changedAt: 'test-system',
          changedBy: 'test-user',
        };
      });

      it('should not render created log-entry', () => {
        expect(spectator.query('.created-timestamp')).not.toBeVisible();
        expect(spectator.query('.created-by')).not.toBeVisible();
        expect(spectator.query('.created-at')).not.toBeVisible();
      });

      it('should render changed-timestamp', () => {
        const date = datePipe.transform(historyMock.changed);
        const time = datePipe.transform(historyMock.changed, 'shortTime');
        const changedTimestamp = date + ' | ' + time + ' Uhr';
        spectator.setInput('historyLogEntryData', historyMock);
        expect(spectator.query('.changed-timestamp')).toHaveText(changedTimestamp);
      });

      it('should render changed-by', () => {
        const changedBy = historyMock.changedBy + ' |';
        spectator.setInput('historyLogEntryData', historyMock);
        expect(spectator.query('.changed-by')).toHaveText(changedBy);
      });

      it('should render changed-at', () => {
        const changedAt = historyMock.changedAt;
        spectator.setInput('historyLogEntryData', historyMock);
        expect(spectator.query('.changed-at')).toHaveText(changedAt);
      });
    });

    describe('type created', () => {
      beforeEach(() => {
        historyMock = {
          created: '2022-11-16T14:49:35.6895',
          createdAt: 'test-system',
          createdBy: 'test-user',
        };
      });

      it('should not render changed log-entry', () => {
        expect(spectator.query('.changed-timestamp')).not.toBeVisible();
        expect(spectator.query('.changed-by')).not.toBeVisible();
        expect(spectator.query('.changed-at')).not.toBeVisible();
      });

      it('should render created-timestamp', () => {
        const date = datePipe.transform(historyMock.created);
        const time = datePipe.transform(historyMock.created, 'shortTime');
        const createdTimestamp = date + ' | ' + time + ' Uhr';
        spectator.setInput('historyLogEntryData', historyMock);
        expect(spectator.query('.created-timestamp')).toHaveText(createdTimestamp);
      });

      it('should render created-by', () => {
        const createdBy = historyMock.createdBy + ' |';
        spectator.setInput('historyLogEntryData', historyMock);
        expect(spectator.query('.created-by')).toHaveText(createdBy);
      });

      it('should render created-at', () => {
        const createdAt = historyMock.createdAt;
        spectator.setInput('historyLogEntryData', historyMock);
        expect(spectator.query('.created-at')).toHaveText(createdAt);
      });
    });

    it('should render log-entry-name if available', () => {
      historyMock = {
        name: 'test-name',
      };
      spectator.setInput('historyLogEntryData', historyMock);
      expect(spectator.query('.log-entry-name')).toHaveText('test-name');
    });

    it('should instead render Geändertes Feld if log-entry-name is not available', () => {
      spectator.setInput('historyLogEntryData', historyMock);
      expect(spectator.query('.log-entry-name')).toHaveText('Geändertes Feld');
    });

    it('should not render old and new value if no log-entry-values are available', () => {
      spectator.setInput('historyLogEntryData', historyMock);
      expect(spectator.query('.old-value')).not.toBeVisible();
      expect(spectator.query('.new-value')).not.toBeVisible();
    });

    it('should render shared-history-log-entry-values if log-entry-values are available', () => {
      historyMock = {
        values: [{}, {}],
      };
      spectator.setInput('historyLogEntryData', historyMock);
      expect(spectator.query('shared-history-log-entry-values')).toBeVisible();
    });

    it('should render shared-history-log-entry-values and set Input historyLogEntryValues', () => {
      const historyLogEntryValues: DiffDTO = { value: 'Test' };
      const history: HistoryDTO = { id: 1, values: [historyLogEntryValues] };
      spectator.setInput('historyLogEntryData', history);
      spectator.detectComponentChanges();
      expect(spectator.query(SharedHistoryLogEntryValuesComponent).historyLogEntryValues).toEqual(
        historyLogEntryValues,
      );
    });
  });
});
