import { ComponentFixture, TestBed } from '@angular/core/testing';
import { describe, it, expect, beforeEach } from 'vitest';
import { OrderConfirmationAddressesComponent } from './order-confirmation-addresses.component';
import { OrderConfiramtionStore } from '../reward-order-confirmation.store';
import { signal } from '@angular/core';
import { DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';

describe('OrderConfirmationAddressesComponent', () => {
  let component: OrderConfirmationAddressesComponent;
  let fixture: ComponentFixture<OrderConfirmationAddressesComponent>;
  let mockStore: {
    payers: ReturnType<typeof signal>;
    shippingAddresses: ReturnType<typeof signal>;
    hasDeliveryOrderTypeFeature: ReturnType<typeof signal>;
    targetBranches: ReturnType<typeof signal>;
    hasTargetBranchFeature: ReturnType<typeof signal>;
  };

  beforeEach(() => {
    // Create mock store with signals
    mockStore = {
      payers: signal([]),
      shippingAddresses: signal([]),
      hasDeliveryOrderTypeFeature: signal(false),
      targetBranches: signal([]),
      hasTargetBranchFeature: signal(false),
    };

    TestBed.configureTestingModule({
      imports: [OrderConfirmationAddressesComponent],
      providers: [
        { provide: OrderConfiramtionStore, useValue: mockStore },
        provideHttpClient(),
      ],
    });

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

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

  it('should render payer address when available', () => {
    // Arrange
    mockStore.payers.set([
      {
        firstName: 'John',
        lastName: 'Doe',
        address: {
          street: 'Main St',
          streetNumber: '123',
          zipCode: '12345',
          city: 'Berlin',
          country: 'DE',
        },
      } as any,
    ]);

    // Act
    fixture.detectChanges();

    // Assert
    const heading = fixture.debugElement.query(By.css('h3'));
    expect(heading).toBeTruthy();
    expect(heading.nativeElement.textContent.trim()).toBe('Rechnungsadresse');

    const customerName = fixture.debugElement.query(
      By.css('.isa-text-body-1-bold.mt-1'),
    );
    expect(customerName).toBeTruthy();
    expect(customerName.nativeElement.textContent.trim()).toContain('John Doe');
  });

  it('should not render payer address when address is missing', () => {
    // Arrange
    mockStore.payers.set([
      {
        firstName: 'John',
        lastName: 'Doe',
        address: undefined,
      } as any,
    ]);

    // Act
    fixture.detectChanges();

    // Assert
    const heading = fixture.debugElement.query(By.css('h3'));
    expect(heading).toBeFalsy();
  });

  it('should render shipping address when hasDeliveryOrderTypeFeature is true', () => {
    // Arrange
    mockStore.hasDeliveryOrderTypeFeature.set(true);
    mockStore.shippingAddresses.set([
      {
        firstName: 'Jane',
        lastName: 'Smith',
        address: {
          street: 'Delivery St',
          streetNumber: '456',
          zipCode: '54321',
          city: 'Hamburg',
          country: 'DE',
        },
      } as any,
    ]);

    // Act
    fixture.detectChanges();

    // Assert
    const headings: DebugElement[] = fixture.debugElement.queryAll(
      By.css('h3'),
    );
    const deliveryHeading = headings.find(
      (h) => h.nativeElement.textContent.trim() === 'Lieferadresse',
    );

    expect(deliveryHeading).toBeTruthy();
  });

  it('should not render shipping address when hasDeliveryOrderTypeFeature is false', () => {
    // Arrange
    mockStore.hasDeliveryOrderTypeFeature.set(false);
    mockStore.shippingAddresses.set([
      {
        firstName: 'Jane',
        lastName: 'Smith',
        address: {
          street: 'Delivery St',
          streetNumber: '456',
          zipCode: '54321',
          city: 'Hamburg',
          country: 'DE',
        },
      } as any,
    ]);

    // Act
    fixture.detectChanges();

    // Assert
    const headings: DebugElement[] = fixture.debugElement.queryAll(
      By.css('h3'),
    );
    const deliveryHeading = headings.find(
      (h) => h.nativeElement.textContent.trim() === 'Lieferadresse',
    );

    expect(deliveryHeading).toBeFalsy();
  });

  it('should render target branch when hasTargetBranchFeature is true', () => {
    // Arrange
    mockStore.hasTargetBranchFeature.set(true);
    mockStore.targetBranches.set([
      {
        name: 'Branch Berlin',
        address: {
          street: 'Branch St',
          streetNumber: '789',
          zipCode: '10115',
          city: 'Berlin',
          country: 'DE',
        },
      } as any,
    ]);

    // Act
    fixture.detectChanges();

    // Assert - Target branch is not yet implemented in the template
    // This test verifies that the component properties are correctly set
    expect(component.hasTargetBranchFeature()).toBe(true);
    expect(component.targetBranches().length).toBe(1);
    expect(component.targetBranches()[0].name).toBe('Branch Berlin');
  });

  it('should not render target branch when hasTargetBranchFeature is false', () => {
    // Arrange
    mockStore.hasTargetBranchFeature.set(false);
    mockStore.targetBranches.set([
      {
        name: 'Branch Berlin',
        address: {
          street: 'Branch St',
          streetNumber: '789',
          zipCode: '10115',
          city: 'Berlin',
          country: 'DE',
        },
      } as any,
    ]);

    // Act
    fixture.detectChanges();

    // Assert
    const headings: DebugElement[] = fixture.debugElement.queryAll(
      By.css('h3'),
    );
    const branchHeading = headings.find(
      (h) => h.nativeElement.textContent.trim() === 'Abholfiliale',
    );

    expect(branchHeading).toBeFalsy();
  });

  it('should render multiple addresses when all features are enabled', () => {
    // Arrange
    mockStore.payers.set([
      {
        firstName: 'John',
        lastName: 'Doe',
        address: {
          street: 'Payer St',
          streetNumber: '1',
          zipCode: '11111',
          city: 'City1',
          country: 'DE',
        },
      } as any,
    ]);
    mockStore.hasDeliveryOrderTypeFeature.set(true);
    mockStore.shippingAddresses.set([
      {
        firstName: 'Jane',
        lastName: 'Smith',
        address: {
          street: 'Delivery St',
          streetNumber: '2',
          zipCode: '22222',
          city: 'City2',
          country: 'DE',
        },
      } as any,
    ]);
    mockStore.hasTargetBranchFeature.set(true);
    mockStore.targetBranches.set([
      {
        name: 'Branch Test',
        address: {
          street: 'Branch St',
          streetNumber: '3',
          zipCode: '33333',
          city: 'City3',
          country: 'DE',
        },
      } as any,
    ]);

    // Act
    fixture.detectChanges();

    // Assert - Only Payer and Shipping addresses are rendered (target branch not yet implemented in template)
    const headings: DebugElement[] = fixture.debugElement.queryAll(
      By.css('h3'),
    );
    expect(headings.length).toBe(2);

    const headingTexts = headings.map((h) =>
      h.nativeElement.textContent.trim(),
    );
    expect(headingTexts).toContain('Rechnungsadresse');
    expect(headingTexts).toContain('Lieferadresse');
  });
});
