import './test-mocks';
import { vi } from 'vitest';
import { describe, it, expect, beforeEach } from 'vitest';
import { TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { RemissionStartService } from './remission-start.service';
import { RemissionStore } from '@isa/remission/data-access';
import { injectDialog } from '@isa/ui/dialog';

describe('RemissionStartService', () => {
  let service: RemissionStartService;
  let mockRemissionStore: any;
  let mockDialog: any;
  let mockDialogRef: any;

  beforeEach(() => {
    // Create mock objects
    mockRemissionStore = {
      startRemission: vi.fn(),
    };

    mockDialogRef = {
      closed: of({ returnId: 'test-return-id', receiptId: 'test-receipt-id' }),
    };

    mockDialog = vi.fn().mockReturnValue(mockDialogRef);

    // Mock the injectDialog function to return our mock dialog
    vi.mocked(injectDialog).mockReturnValue(mockDialog);

    TestBed.configureTestingModule({
      providers: [
        RemissionStartService,
        { provide: RemissionStore, useValue: mockRemissionStore },
      ],
    });

    service = TestBed.inject(RemissionStartService);
  });

  describe('startRemission', () => {
    it('should start remission successfully when dialog returns result', async () => {
      // Arrange
      const returnGroup = 'test-return-group';

      // Act
      await service.startRemission(returnGroup);

      // Assert
      expect(mockDialog).toHaveBeenCalledWith({
        data: { returnGroup },
        classList: ['gap-0'],
        width: '30rem',
      });

      expect(mockRemissionStore.startRemission).toHaveBeenCalledWith({
        returnId: 'test-return-id',
        receiptId: 'test-receipt-id',
      });
    });

    it('should handle undefined returnGroup', async () => {
      // Arrange
      const returnGroup = undefined;

      // Act
      await service.startRemission(returnGroup);

      // Assert
      expect(mockDialog).toHaveBeenCalledWith({
        data: { returnGroup: undefined },
        classList: ['gap-0'],
        width: '30rem',
      });

      expect(mockRemissionStore.startRemission).toHaveBeenCalledWith({
        returnId: 'test-return-id',
        receiptId: 'test-receipt-id',
      });
    });

    it('should not call startRemission when dialog returns falsy result', async () => {
      // Arrange
      const returnGroup = 'test-return-group';
      mockDialogRef.closed = of(null);

      // Act
      await service.startRemission(returnGroup);

      // Assert
      expect(mockDialog).toHaveBeenCalledWith({
        data: { returnGroup },
        classList: ['gap-0'],
        width: '30rem',
      });

      expect(mockRemissionStore.startRemission).not.toHaveBeenCalled();
    });
  });

  describe('assignPackage', () => {
    it('should open dialog with correct assignPackage data and return result', async () => {
      // Arrange
      const returnId = 12345;
      const receiptId = 67890;
      const expectedResult = {
        returnId: 'test-return-id',
        receiptId: 'test-receipt-id',
      };
      mockDialogRef.closed = of(expectedResult);

      // Act
      const result = await service.assignPackage({ returnId, receiptId });

      // Assert
      expect(mockDialog).toHaveBeenCalledWith({
        data: {
          returnGroup: undefined,
          assignPackage: {
            returnId,
            receiptId,
          },
        },
        classList: ['gap-0'],
        width: '30rem',
      });

      expect(result).toEqual(expectedResult);
      expect(mockRemissionStore.startRemission).not.toHaveBeenCalled();
    });

    it('should handle null result from dialog', async () => {
      // Arrange
      const returnId = 12345;
      const receiptId = 67890;
      mockDialogRef.closed = of(null);

      // Act
      const result = await service.assignPackage({ returnId, receiptId });

      // Assert
      expect(mockDialog).toHaveBeenCalledWith({
        data: {
          returnGroup: undefined,
          assignPackage: {
            returnId,
            receiptId,
          },
        },
        classList: ['gap-0'],
        width: '30rem',
      });

      expect(result).toBeNull();
    });
  });
});
