import './test-mocks';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
  RemissionStartDialogComponent,
  ReturnReceiptResultType,
} from './remission-start-dialog.component';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { RemissionReturnReceiptService } from '@isa/remission/data-access';
import { DialogRef, DIALOG_DATA } from '@angular/cdk/dialog';
import { DialogComponent } from '@isa/ui/dialog';
import { describe, it, expect, beforeEach, vi } from 'vitest';

describe('RemissionStartDialogComponent', () => {
  let component: RemissionStartDialogComponent;
  let fixture: ComponentFixture<RemissionStartDialogComponent>;
  let mockRemissionService: {
    createRemission: ReturnType<typeof vi.fn>;
    assignPackage: ReturnType<typeof vi.fn>;
  };
  let mockDialogRef: {
    close: ReturnType<typeof vi.fn>;
  };

  beforeEach(async () => {
    // Mock the dialog ref
    mockDialogRef = {
      close: vi.fn(),
    };

    // Mock dialog data
    const mockDialogData = { returnGroup: 'test-group' };

    // Mock dialog component
    const mockDialogComponent = {
      title: '',
      hideClose: false,
    };

    // Mock remission service
    mockRemissionService = {
      createRemission: vi.fn().mockResolvedValue({
        returnId: 123,
        receiptId: 456,
      }),
      assignPackage: vi.fn().mockResolvedValue({}),
    };

    await TestBed.configureTestingModule({
      imports: [RemissionStartDialogComponent],
      providers: [
        provideHttpClient(),
        provideHttpClientTesting(),
        {
          provide: RemissionReturnReceiptService,
          useValue: mockRemissionService,
        },
        { provide: DialogRef, useValue: mockDialogRef },
        { provide: DIALOG_DATA, useValue: mockDialogData },
        { provide: DialogComponent, useValue: mockDialogComponent },
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(RemissionStartDialogComponent);
    component = fixture.componentInstance;

    // Manually set the dialog data since it's not being injected properly
    (component as any).data = mockDialogData;

    fixture.detectChanges();
  });

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

  describe('onCreateReturnReceipt', () => {
    it('should handle generate receipt type successfully', async () => {
      // Arrange
      const returnReceipt = { type: ReturnReceiptResultType.Generate } as const;

      // Act
      await component.onCreateReturnReceipt(returnReceipt);

      // Assert
      expect(mockRemissionService.createRemission).toHaveBeenCalledWith({
        returnGroup: 'test-group',
        receiptNumber: undefined,
      });
      expect(component.assignPackageStepData()).toEqual({
        returnId: 123,
        receiptId: 456,
      });
      expect(component.createRemissionRequestStatus().loading).toBe(false);
    });

    it('should handle input receipt type with custom receipt number', async () => {
      // Arrange
      const returnReceipt = {
        type: ReturnReceiptResultType.Input,
        value: 'CUSTOM-123',
      };

      // Act
      await component.onCreateReturnReceipt(returnReceipt);

      // Assert
      expect(mockRemissionService.createRemission).toHaveBeenCalledWith({
        returnGroup: 'test-group',
        receiptNumber: 'CUSTOM-123',
      });
      expect(component.assignPackageStepData()).toEqual({
        returnId: 123,
        receiptId: 456,
      });
      expect(component.createRemissionRequestStatus().loading).toBe(false);
    });

    it('should handle input receipt type with null value', async () => {
      // Arrange
      const returnReceipt = {
        type: ReturnReceiptResultType.Input,
        value: null,
      };

      // Act
      await component.onCreateReturnReceipt(returnReceipt);

      // Assert
      expect(mockRemissionService.createRemission).toHaveBeenCalledWith({
        returnGroup: 'test-group',
        receiptNumber: undefined,
      });
      expect(component.assignPackageStepData()).toEqual({
        returnId: 123,
        receiptId: 456,
      });
    });

    it('should close dialog when receipt type is close', async () => {
      // Arrange
      const closeSpy = vi.spyOn(component, 'onDialogClose');
      const returnReceipt = { type: ReturnReceiptResultType.Close } as const;

      // Act
      await component.onCreateReturnReceipt(returnReceipt);

      // Assert
      expect(closeSpy).toHaveBeenCalledWith(undefined);
      expect(mockRemissionService.createRemission).not.toHaveBeenCalled();
    });
  });

  describe('onAssignPackageNumber', () => {
    it('should assign package number successfully', async () => {
      // Arrange
      const packageNumber = 'PKG-789';
      component.assignPackageStepData.set({
        returnId: 123,
        receiptId: 456,
      });
      const closeSpy = vi.spyOn(component, 'onDialogClose');

      // Act
      await component.onAssignPackageNumber(packageNumber);

      // Assert
      expect(mockRemissionService.assignPackage).toHaveBeenCalledWith({
        packageNumber: 'PKG-789',
        returnId: 123,
        receiptId: 456,
      });
      expect(closeSpy).toHaveBeenCalledWith({
        returnId: 123,
        receiptId: 456,
      });
    });

    it('should close dialog when no package number provided', async () => {
      // Arrange
      const closeSpy = vi.spyOn(component, 'onDialogClose');
      component.assignPackageStepData.set({
        returnId: 123,
        receiptId: 456,
      });

      // Act
      await component.onAssignPackageNumber(undefined);

      // Assert
      expect(closeSpy).toHaveBeenCalledWith(undefined);
      expect(mockRemissionService.assignPackage).not.toHaveBeenCalled();
    });

    it('should close dialog when no step data available', async () => {
      // Arrange
      const closeSpy = vi.spyOn(component, 'onDialogClose');
      component.assignPackageStepData.set(undefined);

      // Act
      await component.onAssignPackageNumber('PKG-789');

      // Assert
      expect(closeSpy).toHaveBeenCalledWith(undefined);
      expect(mockRemissionService.assignPackage).not.toHaveBeenCalled();
    });
  });

  describe('onDialogClose', () => {
    it('should close dialog with result', () => {
      // Arrange
      const result = { returnId: 123, receiptId: 456 };
      const closeSpy = vi.spyOn(component, 'close');

      // Act
      component.onDialogClose(result);

      // Assert
      expect(closeSpy).toHaveBeenCalledWith(result);
    });

    it('should close dialog with undefined result', () => {
      // Arrange
      const closeSpy = vi.spyOn(component, 'close');

      // Act
      component.onDialogClose(undefined);

      // Assert
      expect(closeSpy).toHaveBeenCalledWith(undefined);
    });
  });
});
