/*
 * Copyright (C) 2023 Robert Bosch GmbH Copyright (C) 2023 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import { ComponentFixture, TestBed } from '@angular/core/testing';

import { BrowserAnimationsModule, NoopAnimationsModule } from "@angular/platform-browser/animations";
import { matchDurationWithDurationType } from "./bci-duration-picker.helper";
// eslint-disable-next-line @nx/enforce-module-boundaries
import { BciDurationPickerComponent, DurationType } from "@bci-web-core/core";


describe('BciDurationPickerComponent', () => {
  let component: BciDurationPickerComponent;
  let fixture: ComponentFixture<BciDurationPickerComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        BciDurationPickerComponent,
        BrowserAnimationsModule,
        NoopAnimationsModule
      ]
    })
      .compileComponents();

    fixture = TestBed.createComponent(BciDurationPickerComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  function clickSuffixBtn(): void {
    const suffixButton = fixture.nativeElement.querySelector('.suffix-btn');
    suffixButton.click();
  }

  function checkClosedPanelRelatedFlags(): void {
    expect(component.isPanelOpen).toBeFalsy();
    expect(component.inputTouched).toBeFalsy();
  }

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

  it('should be match between duration and durationType', (): void => {
    const matching: boolean = matchDurationWithDurationType(component.duration, component.durationType);

    expect(matching).toBeTruthy();
  });

  it('should open panel when click inside the duration picker', (): void => {
    const durationPickerArea = fixture.nativeElement.querySelector('input');
    durationPickerArea.click();
    fixture.detectChanges();

    expect(component.panelOpen).toBeTruthy();
  });

  it('should open panel by clicking into suffix button', (): void => {
    clickSuffixBtn();

    expect(component.panelOpen).toBeTruthy();
  });

  it('should not open dropdown if Duration Picker is disabled', (): void => {
    component.disabled = true;
    component.openPanel();

    expect(component.isPanelOpen).toBeFalsy();
  });

  it('should close panel when click outside the duration picker', (): void => {
    component.panelOpen = true;
    document.body.click();

    expect(component.panelOpen).toBeFalsy();
  });

  it('should close panel if user clicks on the suffix icon to close the panel', (): void => {
    component.inputDirty = false;
    component.panelOpen = true;
    component.inputTouched = true;
    fixture.detectChanges();

    clickSuffixBtn();

    expect(component.panelOpen).toBeFalsy();
    expect(component.inputTouched).toBeFalsy();
  });

  it('should reset duration if user clicks into suffix icon to reset the duration', (): void => {
    component.inputDirty = true;
    component.panelOpen = true;
    fixture.detectChanges();

    clickSuffixBtn();

    expect(component.inputDirty).toBeFalsy();
    expect(component.bindDuration).toBeNull();
  });

  it('should take correct picker values', (): void => {
    component.takePickerValue(1, 'days');
    component.takePickerValue(1, 'hours');
    component.takePickerValue(1, 'minutes');
    component.takePickerValue(1, 'seconds');
    expect(component.encapsulatedDuration).toEqual({
      days: 1,
      hours: 1,
      minutes: 1,
      seconds: 1
    });
  });

  it('should handle type structure', (): void => {
    // default type structure
    expect(component.typeStructure).toEqual({
      days: true,
      hours: true,
      minutes: true,
      seconds: true
    });
    expect(component.onlyOnePicker).toBeFalsy();

    // two pickers structure
    component.durationType = DurationType['HH:MM'];
    component['handleTypeStructure']();
    expect(component.typeStructure).toEqual({
      days: false,
      hours: true,
      minutes: true,
      seconds: false
    });
    expect(component.onlyOnePicker).toBeFalsy();

    // wrong durationType structure
    component.durationType = DurationType['werwerwerwer'];
    component['handleTypeStructure']();
    expect(component.typeStructure).toEqual({
      days: true,
      hours: true,
      minutes: true,
      seconds: true
    });
    expect(component.onlyOnePicker).toBeFalsy();

    // only one picker
    component.durationType = DurationType['HH'];
    component['handleTypeStructure']();
    expect(component.typeStructure).toEqual({
      days: false,
      hours: true,
      minutes: false,
      seconds: false
    });
    expect(component.onlyOnePicker).toBeTruthy();
  });

  it('should show notification if pattern not respected', (): void => {
    component.inputDirty = true;
    component.bindDuration = 'something_wrong';
    component.closePanel();

    checkClosedPanelRelatedFlags();
    expect(component.inputNotMatching).toBeTruthy();
  });

  it('should show notification if types not matching', (): void => {
    component.inputDirty = true;
    component.bindDuration = '123.23:59';
    component.closePanel();

    checkClosedPanelRelatedFlags();
    expect(component.inputNotMatching).toBeTruthy();
  });

  it('should autofill with 0 the duration', (): void => {
    component.inputDirty = true;
    component.bindDuration = '123';
    component.closePanel();

    checkClosedPanelRelatedFlags();
    expect(component.encapsulatedDuration).toMatchObject({
      days: 123,
      hours: 0,
      minutes: 0,
      seconds: 0
    });
  });

  it('should fit input value to max number of durations', (): void => {
    component.inputDirty = true;
    component.bindDuration = '123.999:999:999';
    component.closePanel();

    checkClosedPanelRelatedFlags();
    expect(component.encapsulatedDuration).toMatchObject({
      days: 123,
      hours: 23,
      minutes: 59,
      seconds: 59
    });
  });

  it('should filter null values from object', (): void => {
    expect(component["filterObjectDurationNullProperties"]({days: null})).toMatchObject({days: 0});
    expect(component["filterObjectDurationNullProperties"]({days: null, hours: 10})).toMatchObject({days: 0, hours: 10});
  });
});
