import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ResourceRef } from '@angular/core';
import { vi } from 'vitest';
import { CountryResource } from '@isa/crm/data-access';
import { InlineAddressComponent } from './inline-address.component';
import { Address } from './types';

describe('InlineAddressComponent', () => {
  let component: InlineAddressComponent;
  let fixture: ComponentFixture<InlineAddressComponent>;
  let mockCountryResource: CountryResource;

  beforeEach(async () => {
    const mockResourceRef = {
      value: vi.fn().mockReturnValue([
        { isO3166_A_3: 'FRA', name: 'France' },
        { isO3166_A_3: 'AUT', name: 'Austria' },
        { isO3166_A_3: 'USA', name: 'United States' },
      ]),
      isLoading: vi.fn().mockReturnValue(false),
      hasValue: vi.fn().mockReturnValue(true),
      error: vi.fn().mockReturnValue(null),
      status: vi.fn().mockReturnValue('Resolved'),
      reload: vi.fn(),
    } as unknown as ResourceRef<any>;

    mockCountryResource = {
      resource: mockResourceRef,
    } as CountryResource;

    await TestBed.configureTestingModule({
      imports: [InlineAddressComponent],
      providers: [{ provide: CountryResource, useValue: mockCountryResource }],
    }).compileComponents();

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

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

  describe('Complete address display', () => {
    it('should display address in inline format', () => {
      // Arrange
      const address: Address = {
        street: 'Main Street',
        streetNumber: '42',
        zipCode: '12345',
        city: 'Berlin',
        country: 'DEU',
      };
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('Main Street 42, 12345 Berlin');
    });
  });

  describe('German address handling', () => {
    it('should not display country for DEU', () => {
      // Arrange
      const address: Address = {
        street: 'Hauptstraße',
        streetNumber: '10',
        zipCode: '80331',
        city: 'München',
        country: 'DEU',
      };
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('Hauptstraße 10, 80331 München');
      expect(compiled.textContent).not.toContain('DEU');
    });
  });

  describe('Non-German address handling', () => {
    it('should display country name from country code for non-German addresses', () => {
      // Arrange
      const address: Address = {
        street: 'Rue de la Paix',
        streetNumber: '15',
        zipCode: '75002',
        city: 'Paris',
        country: 'FRA',
      };
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('Rue de la Paix 15, 75002 Paris, France');
    });

    it('should display country name for Austrian addresses', () => {
      // Arrange
      const address: Address = {
        street: 'Stephansplatz',
        streetNumber: '1',
        zipCode: '1010',
        city: 'Wien',
        country: 'AUT',
      };
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('Stephansplatz 1, 1010 Wien, Austria');
    });

    it('should fallback to country code when country name not found', () => {
      // Arrange
      const address: Address = {
        street: 'Unknown Street',
        streetNumber: '1',
        zipCode: '12345',
        city: 'Unknown City',
        country: 'XYZ',
      };
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('Unknown Street 1, 12345 Unknown City, XYZ');
    });
  });

  describe('Partial addresses', () => {
    it('should handle address with only street and number', () => {
      // Arrange
      const address: Address = {
        street: 'Test Street',
        streetNumber: '99',
      };
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('Test Street 99');
    });

    it('should handle address with only city information', () => {
      // Arrange
      const address: Address = {
        zipCode: '12345',
        city: 'City Only',
      };
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('12345 City Only');
    });

    it('should handle address with street and city but no zip', () => {
      // Arrange
      const address: Address = {
        street: 'Main Street',
        streetNumber: '5',
        city: 'TestCity',
      };
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('Main Street 5, TestCity');
    });
  });

  describe('Empty or undefined address', () => {
    it('should not render anything when address is undefined', () => {
      // Arrange
      fixture.componentRef.setInput('address', undefined);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('');
    });

    it('should not render anything when address is empty object', () => {
      // Arrange
      const address: Address = {};
      fixture.componentRef.setInput('address', address);

      // Act
      fixture.detectChanges();

      // Assert
      const compiled = fixture.nativeElement as HTMLElement;
      expect(compiled.textContent?.trim()).toBe('');
    });
  });
});