import { ComponentFixture, TestBed } from '@angular/core/testing';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { Component, signal } from '@angular/core';
import { RemissionReturnReceiptListComponent } from './remission-return-receipt-list.component';
import { Return, Receipt } from '@isa/remission/data-access';
import { FilterService } from '@isa/shared/filter';

// Mock the filter providers
vi.mock('@isa/shared/filter', async () => {
  const actual = await vi.importActual('@isa/shared/filter');
  return {
    ...actual,
    provideFilter: vi.fn(() => []),
    withQueryParamsSync: vi.fn(() => ({})),
    withQuerySettings: vi.fn(() => ({})),
  };
});

// Mock the resources
vi.mock('./resources', () => ({
  completedRemissionReturnsResource: vi.fn(),
  incompletedRemissionReturnsResource: vi.fn(),
}));

// Mock child components
@Component({
  selector: 'remi-return-receipt-list-item',
  template: '<div>Mock Return Receipt List Item</div>',
  standalone: true,
})
class MockReturnReceiptListItemComponent {}

@Component({
  selector: 'remi-remission-return-receipt-list-card',
  template: '<div>Mock Return Receipt List Card</div>',
  standalone: true,
})
class MockRemissionReturnReceiptListCardComponent {}

@Component({
  selector: 'isa-filter-controls-panel',
  template: '<div>Mock Filter Controls Panel</div>',
  standalone: true,
})
class MockFilterControlsPanelComponent {}

describe('RemissionReturnReceiptListComponent', () => {
  let component: RemissionReturnReceiptListComponent;
  let fixture: ComponentFixture<RemissionReturnReceiptListComponent>;
  let mockFilterService: any;
  let mockCompletedResource: any;
  let mockIncompletedResource: any;

  const mockCompletedReturn: Return = {
    id: 1,
    completed: '2024-01-15T10:30:00.000Z',
    receipts: [
      {
        id: 101,
        data: {
          id: 101,
          receiptNumber: 'REC-2024-001',
          created: '2024-01-15T09:00:00.000Z',
          completed: '2024-01-15T10:30:00.000Z',
          items: [],
        } as Receipt,
      },
    ],
  } as Return;

  const mockIncompletedReturn: Return = {
    id: 2,
    completed: undefined,
    receipts: [
      {
        id: 102,
        data: {
          id: 102,
          receiptNumber: 'REC-2024-002',
          created: '2024-01-16T08:00:00.000Z',
          completed: undefined,
          items: [],
        } as Receipt,
      },
    ],
  } as Return;

  beforeEach(async () => {
    // Setup mocks
    mockFilterService = {
      orderBy: signal([]),
      inputs: signal([]),
      groups: signal([]),
      queryParams: signal({}),
      query: signal({ filter: {}, input: {}, orderBy: [] }),
      isEmpty: signal(true),
      isDefaultFilter: signal(true),
      selectedFilterCount: signal(0),
    };

    mockCompletedResource = {
      value: vi.fn().mockReturnValue([mockCompletedReturn]),
      reload: vi.fn(),
      isLoading: vi.fn().mockReturnValue(false),
    };

    mockIncompletedResource = {
      value: vi.fn().mockReturnValue([mockIncompletedReturn]),
      reload: vi.fn(),
      isLoading: vi.fn().mockReturnValue(false),
    };

    // Mock the resource functions
    const {
      completedRemissionReturnsResource,
      incompletedRemissionReturnsResource,
    } = await import('./resources');
    vi.mocked(completedRemissionReturnsResource).mockReturnValue(
      mockCompletedResource,
    );
    vi.mocked(incompletedRemissionReturnsResource).mockReturnValue(
      mockIncompletedResource,
    );

    await TestBed.configureTestingModule({
      imports: [RemissionReturnReceiptListComponent],
      providers: [{ provide: FilterService, useValue: mockFilterService }],
    })
      .overrideComponent(RemissionReturnReceiptListComponent, {
        remove: {
          imports: [
            // Remove original components
          ],
        },
        add: {
          imports: [
            MockReturnReceiptListItemComponent,
            MockRemissionReturnReceiptListCardComponent,
            MockFilterControlsPanelComponent,
          ],
        },
      })
      .compileComponents();

    fixture = TestBed.createComponent(RemissionReturnReceiptListComponent);
    component = fixture.componentInstance;
  });

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

    it('should initialize resources', () => {
      expect(component.completedRemissionReturnsResource).toBeDefined();
      expect(component.incompletedRemissionReturnsResource).toBeDefined();
    });
  });

  describe('orderDateBy computed signal', () => {
    it('should return undefined when no order is selected', () => {
      mockFilterService.orderBy.set([]);

      const orderBy = component.orderDateBy();

      expect(orderBy).toBeUndefined();
    });

    it('should return selected order option', () => {
      const selectedOrder = { selected: true, by: 'created', dir: 'desc' };
      mockFilterService.orderBy.set([selectedOrder]);

      const orderBy = component.orderDateBy();

      expect(orderBy).toBe(selectedOrder);
    });
  });

  describe('returns computed signal', () => {
    it('should combine completed and incompleted returns', () => {
      const returns = component.returns();

      expect(returns).toHaveLength(2);
      expect(returns[0][0]).toBe(mockIncompletedReturn);
      expect(returns[0][1]).toBe(mockIncompletedReturn.receipts[0].data);
      expect(returns[1][0]).toBe(mockCompletedReturn);
      expect(returns[1][1]).toBe(mockCompletedReturn.receipts[0].data);
    });

    it('should handle empty returns', () => {
      mockCompletedResource.value.mockReturnValue([]);
      mockIncompletedResource.value.mockReturnValue([]);

      const returns = component.returns();

      expect(returns).toHaveLength(0);
    });
  });

  describe('reloadList method', () => {
    it('should reload both resources', () => {
      component.reloadList();

      expect(mockCompletedResource.reload).toHaveBeenCalled();
      expect(mockIncompletedResource.reload).toHaveBeenCalled();
    });
  });
});
