import { ComponentFixture, TestBed } from '@angular/core/testing'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { Subject } from 'rxjs'
import { ConfirmDialogComponent } from './confirm-dialog.component'

describe('ConfirmDialogComponent', () => {
  let component: ConfirmDialogComponent
  let modal: NgbActiveModal
  let fixture: ComponentFixture<ConfirmDialogComponent>

  beforeEach(async () => {
    TestBed.configureTestingModule({
      providers: [NgbActiveModal],
      imports: [ConfirmDialogComponent],
    }).compileComponents()

    modal = TestBed.inject(NgbActiveModal)

    fixture = TestBed.createComponent(ConfirmDialogComponent)
    component = fixture.componentInstance
    component.title = 'Confirm delete'
    component.messageBold = 'Do you really want to delete document file.pdf?'
    component.message =
      'The files for this document will be deleted permanently. This operation cannot be undone.'
    component.btnClass = 'btn-danger'
    component.btnCaption = 'Delete document'

    fixture.detectChanges()
  })

  it('should support alternative', () => {
    let alternativeClickedResult
    let alternativeSubjectResult
    component.alternativeClicked.subscribe((result) => {
      alternativeClickedResult = true
    })
    component.alternative()
    // with subject
    const subject = new Subject<boolean>()
    component.alternativeSubject = subject
    subject.asObservable().subscribe((result) => {
      alternativeSubjectResult = result
    })
    component.alternative()
    expect(alternativeClickedResult).toBeTruthy()
    expect(alternativeSubjectResult).toBeTruthy()
  })

  it('should support confirm', () => {
    let confirmClickedResult
    let confirmSubjectResult
    component.confirmClicked.subscribe((result) => {
      confirmClickedResult = true
    })
    component.confirm()
    // with subject
    const subject = new Subject<boolean>()
    component.confirmSubject = subject
    subject.asObservable().subscribe((result) => {
      confirmSubjectResult = result
    })
    component.confirm()
    expect(confirmClickedResult).toBeTruthy()
    expect(confirmSubjectResult).toBeTruthy()
  })

  it('should re-render the buttons when they are toggled from outside', async () => {
    const confirmButton: HTMLButtonElement =
      fixture.nativeElement.querySelectorAll('.modal-footer button')[1]
    expect(confirmButton.disabled).toBeFalsy()

    // Deliberately no detectChanges: a request callback toggling this is all
    // that happens, and nothing else schedules a render for the modal
    component.buttonsEnabled.set(false)
    await fixture.whenStable()
    expect(confirmButton.disabled).toBeTruthy()

    component.buttonsEnabled.set(true)
    await fixture.whenStable()
    expect(confirmButton.disabled).toBeFalsy()
  })

  it('should support cancel & close modal', () => {
    let confirmSubjectResult
    const closeModalSpy = jest.spyOn(modal, 'close')
    component.cancel()
    const subject = new Subject<boolean>()
    component.confirmSubject = subject
    subject.asObservable().subscribe((result) => {
      confirmSubjectResult = result
    })
    component.cancel()
    // with subject
    expect(closeModalSpy).toHaveBeenCalled()
    expect(confirmSubjectResult).toBeFalsy()
  })
})
