import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { of, throwError } from 'rxjs';
import { CashboxExportApi } from '../../../../core/team/cashbox-export-api';
import { CashboxExportSubscriptionDialog } from './cashbox-export-subscription-dialog';

describe('CashboxExportSubscriptionDialog', () => {
  let fixture: ComponentFixture<CashboxExportSubscriptionDialog>;
  let getSubscription: ReturnType<typeof vi.fn>;
  let updateSubscription: ReturnType<typeof vi.fn>;
  let dialogRef: { close: ReturnType<typeof vi.fn> };

  beforeEach(async () => {
    getSubscription = vi.fn(() =>
      of({ recipients: ['a@example.com'], interval: 'monthly', active: true, nextRunDate: '2026-09-01T00:00:00.000Z' }),
    );
    updateSubscription = vi.fn(() =>
      of({ recipients: ['a@example.com', 'b@example.com'], interval: 'monthly', active: true, nextRunDate: '2026-09-01T00:00:00.000Z' }),
    );
    dialogRef = { close: vi.fn() };

    await TestBed.configureTestingModule({
      imports: [CashboxExportSubscriptionDialog],
      providers: [
        { provide: MAT_DIALOG_DATA, useValue: { teamId: 5 } },
        { provide: MatDialogRef, useValue: dialogRef },
        { provide: CashboxExportApi, useValue: { getSubscription, updateSubscription } },
      ],
    }).compileComponents();
    fixture = TestBed.createComponent(CashboxExportSubscriptionDialog);
    fixture.detectChanges();
  });

  it('loads the existing subscription into the form', () => {
    expect(getSubscription).toHaveBeenCalledWith(5);
    expect(fixture.componentInstance['recipients']()).toEqual(['a@example.com']);
  });

  it('rejects adding an invalid email', () => {
    fixture.componentInstance['addRecipient']('not-an-email');
    expect(fixture.componentInstance['recipients']()).toEqual(['a@example.com']);
  });

  it('adds a valid email and saves the updated recipient list', () => {
    fixture.componentInstance['addRecipient']('b@example.com');
    expect(fixture.componentInstance['recipients']()).toEqual(['a@example.com', 'b@example.com']);

    fixture.componentInstance['save']();

    expect(updateSubscription).toHaveBeenCalledWith(5, {
      recipients: ['a@example.com', 'b@example.com'],
      interval: 'monthly',
      active: true,
    });
    expect(dialogRef.close).toHaveBeenCalled();
  });

  it('removes a recipient', () => {
    fixture.componentInstance['removeRecipient']('a@example.com');
    expect(fixture.componentInstance['recipients']()).toEqual([]);
  });

  it('handles getSubscription error by setting loadError', async () => {
    getSubscription.mockReturnValueOnce(throwError(() => new Error('API error')));

    await TestBed.resetTestingModule();
    await TestBed.configureTestingModule({
      imports: [CashboxExportSubscriptionDialog],
      providers: [
        { provide: MAT_DIALOG_DATA, useValue: { teamId: 5 } },
        { provide: MatDialogRef, useValue: dialogRef },
        { provide: CashboxExportApi, useValue: { getSubscription, updateSubscription } },
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(CashboxExportSubscriptionDialog);
    fixture.detectChanges();

    expect(fixture.componentInstance['loadError']()).toBe('Einstellungen konnten nicht geladen werden.');
  });

  it('handles updateSubscription error by setting saveError and not closing dialog', () => {
    updateSubscription.mockReturnValueOnce(throwError(() => new Error('API error')));
    dialogRef.close.mockClear();

    fixture.componentInstance['addRecipient']('b@example.com');
    fixture.componentInstance['save']();

    expect(fixture.componentInstance['saveError']()).toBe('Speichern fehlgeschlagen.');
    expect(dialogRef.close).not.toHaveBeenCalled();
  });
});
