import { ComponentFixture, TestBed } from '@angular/core/testing';
import { describe, it, expect, beforeEach } from 'vitest';
import { OrderConfirmationItemListItemComponent } from './order-confirmation-item-list-item.component';
import { DisplayOrderItem, DisplayOrder } from '@isa/oms/data-access';
import { DebugElement, signal } from '@angular/core';
import { By } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { provideProductImageUrl } from '@isa/shared/product-image';
import { provideProductRouterLinkBuilder } from '@isa/shared/product-router-link';
import { provideHttpClient } from '@angular/common/http';
import { OrderConfiramtionStore } from '../../reward-order-confirmation.store';

describe('OrderConfirmationItemListItemComponent', () => {
  let component: OrderConfirmationItemListItemComponent;
  let fixture: ComponentFixture<OrderConfirmationItemListItemComponent>;
  let mockStore: {
    orders: ReturnType<typeof signal>;
  };

  const mockOrder: DisplayOrder = {
    id: 1,
    orderNumber: 'ORD-123',
    orderType: 'Reward',
    status: 'Confirmed',
  } as DisplayOrder;

  beforeEach(() => {
    // Create mock store
    mockStore = {
      orders: signal([mockOrder]),
    };

    TestBed.configureTestingModule({
      imports: [OrderConfirmationItemListItemComponent],
      providers: [
        { provide: OrderConfiramtionStore, useValue: mockStore },
        provideRouter([]),
        provideProductImageUrl('https://test.example.com'),
        provideProductRouterLinkBuilder((ean: string) => `/product/${ean}`),
        provideHttpClient(),
      ],
    });

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

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

  describe('productItem computed signal', () => {
    it('should return product from item', () => {
      // Arrange
      const item: DisplayOrderItem = {
        id: 1,
        quantity: 2,
        product: {
          ean: '1234567890123',
          name: 'Test Product',
          contributors: 'Test Author',
          catalogProductNumber: 'CAT-123',
        },
      } as DisplayOrderItem;

      // Act
      fixture.componentRef.setInput('item', item);
      fixture.componentRef.setInput('order', mockOrder);

      // Assert
      expect(component.productItem()).toEqual({
        ean: '1234567890123',
        name: 'Test Product',
        contributors: 'Test Author',
        catalogProductNumber: 'CAT-123',
      });
    });

    it('should return undefined when item has no product', () => {
      // Arrange
      const item: DisplayOrderItem = {
        id: 1,
        quantity: 1,
      } as DisplayOrderItem;

      // Act
      fixture.componentRef.setInput('item', item);
      fixture.componentRef.setInput('order', mockOrder);

      // Assert
      expect(component.productItem()).toBeUndefined();
    });
  });

  describe('points computed signal', () => {
    it('should return loyalty points from item', () => {
      // Arrange
      const item: DisplayOrderItem = {
        id: 1,
        quantity: 1,
        product: {
          catalogProductNumber: 'CAT-123',
          ean: '1234567890123',
        },
        loyalty: { value: 150 },
      } as DisplayOrderItem;

      // Act
      fixture.componentRef.setInput('item', item);
      fixture.componentRef.setInput('order', mockOrder);

      // Assert
      expect(component.points()).toBe(150);
    });

    it('should return 0 when loyalty is missing', () => {
      // Arrange
      const item: DisplayOrderItem = {
        id: 1,
        quantity: 1,
        product: {
          catalogProductNumber: 'CAT-123',
        },
      } as DisplayOrderItem;

      // Act
      fixture.componentRef.setInput('item', item);
      fixture.componentRef.setInput('order', mockOrder);

      // Assert
      expect(component.points()).toBe(0);
    });

    it('should return 0 when loyalty value is missing', () => {
      // Arrange
      const item: DisplayOrderItem = {
        id: 1,
        quantity: 1,
        product: {
          catalogProductNumber: 'CAT-123',
        },
        loyalty: {},
      } as DisplayOrderItem;

      // Act
      fixture.componentRef.setInput('item', item);
      fixture.componentRef.setInput('order', mockOrder);

      // Assert
      expect(component.points()).toBe(0);
    });
  });

  describe('template rendering', () => {
    it('should render product points with E2E attribute', () => {
      // Arrange
      const item: DisplayOrderItem = {
        id: 1,
        quantity: 2,
        product: {
          ean: '1234567890123',
          name: 'Test Product',
          contributors: 'Test Author',
          catalogProductNumber: 'CAT-123',
        },
        loyalty: { value: 200 },
      } as DisplayOrderItem;

      // Act
      fixture.componentRef.setInput('item', item);
      fixture.componentRef.setInput('order', mockOrder);
      fixture.detectChanges();

      // Assert
      const pointsElement: DebugElement = fixture.debugElement.query(
        By.css('[data-what="product-points"]')
      );
      expect(pointsElement).toBeTruthy();
      expect(pointsElement.nativeElement.textContent.trim()).toContain('200');
      expect(pointsElement.nativeElement.textContent.trim()).toContain('Lesepunkte');
    });

    it('should render quantity', () => {
      // Arrange
      const item: DisplayOrderItem = {
        id: 1,
        quantity: 5,
        product: {
          ean: '1234567890123',
          name: 'Test Product',
          catalogProductNumber: 'CAT-123',
        },
      } as DisplayOrderItem;

      // Act
      fixture.componentRef.setInput('item', item);
      fixture.componentRef.setInput('order', mockOrder);
      fixture.detectChanges();

      // Assert
      const quantityElements = fixture.debugElement.queryAll(
        By.css('.isa-text-body-2-bold')
      );
      const quantityElement = quantityElements.find((el) =>
        el.nativeElement.textContent.includes('x')
      );

      expect(quantityElement).toBeTruthy();
      expect(quantityElement!.nativeElement.textContent.trim()).toBe('5 x');
    });

    it('should render all child components', () => {
      // Arrange
      const item: DisplayOrderItem = {
        id: 1,
        quantity: 1,
        product: {
          ean: '1234567890123',
          name: 'Test Product',
          catalogProductNumber: 'CAT-123',
        },
      } as DisplayOrderItem;

      // Act
      fixture.componentRef.setInput('item', item);
      fixture.componentRef.setInput('order', mockOrder);
      fixture.detectChanges();

      // Assert
      const productInfo = fixture.debugElement.query(By.css('checkout-product-info'));
      const actionCard = fixture.debugElement.query(
        By.css('checkout-confirmation-list-item-action-card')
      );
      const destinationInfo = fixture.debugElement.query(
        By.css('checkout-display-order-destination-info')
      );

      expect(productInfo).toBeTruthy();
      expect(actionCard).toBeTruthy();
      expect(destinationInfo).toBeTruthy();
    });
  });
});
