import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { DomSanitizer } from '@angular/platform-browser';
import { EmptyStateComponent } from './empty-state.component';
import { EmptyStateAppearance } from './types';
import {
  NO_RESULTS,
  NO_ARTICLES,
  ALL_DONE_CUP,
  ALL_DONE_FUME,
  SELECT_ACTION_HAND,
  SELECT_ACTION_OBJECT_DROPDOWN,
} from './constants';

describe('EmptyStateComponent', () => {
  let spectator: Spectator<EmptyStateComponent>;
  let mockSanitizer: jest.Mocked<DomSanitizer>;

  const createComponent = createComponentFactory({
    component: EmptyStateComponent,
    providers: [
      {
        provide: DomSanitizer,
        useValue: {
          bypassSecurityTrustHtml: jest.fn(),
          bypassSecurityTrustStyle: jest.fn(),
          bypassSecurityTrustScript: jest.fn(),
          bypassSecurityTrustUrl: jest.fn(),
          bypassSecurityTrustResourceUrl: jest.fn(),
          sanitize: jest.fn(),
        },
      },
    ],
  });

  beforeEach(() => {
    spectator = createComponent({
      props: {
        title: 'Test Title',
        description: 'Test Description',
      },
    });
    mockSanitizer = spectator.inject(DomSanitizer) as jest.Mocked<DomSanitizer>;

    // Clear any calls made during component initialization
    mockSanitizer.bypassSecurityTrustHtml.mockClear();
  });

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

  it('should set title and description inputs correctly', () => {
    expect(spectator.component.title()).toEqual('Test Title');
    expect(spectator.component.description()).toEqual('Test Description');
  });

  it('should apply the host class "ui-empty-state"', () => {
    expect(spectator.element.classList.contains('ui-empty-state')).toBe(true);
  });

  it('should have default appearance as NoResults', () => {
    expect(spectator.component.appearance()).toBe(
      EmptyStateAppearance.NoResults,
    );
  });

  it('should set appearance input correctly', () => {
    spectator.setInput('appearance', EmptyStateAppearance.AllDone);
    expect(spectator.component.appearance()).toBe(EmptyStateAppearance.AllDone);
  });

  describe('icon computed property', () => {
    it('should return NO_RESULTS icon for NoResults appearance', () => {
      spectator.setInput('appearance', EmptyStateAppearance.NoResults);
      expect(spectator.component.icon()).toBe(NO_RESULTS);
    });

    it('should return NO_ARTICLES icon for NoArticles appearance', () => {
      spectator.setInput('appearance', EmptyStateAppearance.NoArticles);
      expect(spectator.component.icon()).toBe(NO_ARTICLES);
    });

    it('should return ALL_DONE_CUP icon for AllDone appearance', () => {
      spectator.setInput('appearance', EmptyStateAppearance.AllDone);
      expect(spectator.component.icon()).toBe(ALL_DONE_CUP);
    });

    it('should return SELECT_ACTION_OBJECT_DROPDOWN icon for SelectAction appearance', () => {
      spectator.setInput('appearance', EmptyStateAppearance.SelectAction);
      expect(spectator.component.icon()).toBe(SELECT_ACTION_OBJECT_DROPDOWN);
    });

    it('should return NO_RESULTS icon for default case', () => {
      expect(spectator.component.icon()).toBe(NO_RESULTS);
    });
  });

  describe('subIcon computed property', () => {
    it('should return ALL_DONE_FUME for AllDone appearance', () => {
      spectator.setInput('appearance', EmptyStateAppearance.AllDone);
      expect(spectator.component.subIcon()).toBe(ALL_DONE_FUME);
    });

    it('should return SELECT_ACTION_HAND for SelectAction appearance', () => {
      spectator.setInput('appearance', EmptyStateAppearance.SelectAction);
      expect(spectator.component.subIcon()).toBe(SELECT_ACTION_HAND);
    });

    it('should return empty string for NoResults appearance', () => {
      spectator.setInput('appearance', EmptyStateAppearance.NoResults);
      expect(spectator.component.subIcon()).toBe('');
    });

    it('should return empty string for NoArticles appearance', () => {
      spectator.setInput('appearance', EmptyStateAppearance.NoArticles);
      expect(spectator.component.subIcon()).toBe('');
    });
  });

  describe('sanitizedSubIcon computed property', () => {
    it('should return sanitized subIcon when subIcon has content', () => {
      // Arrange
      const mockSafeHtml = { toString: () => 'sanitized-sub-icon' };
      mockSanitizer.bypassSecurityTrustHtml.mockReturnValue(
        mockSafeHtml as any,
      );
      spectator.setInput('appearance', EmptyStateAppearance.AllDone);

      // Act
      const result = spectator.component.sanitizedSubIcon();

      // Assert
      expect(mockSanitizer.bypassSecurityTrustHtml).toHaveBeenCalledWith(
        ALL_DONE_FUME,
      );
      expect(result).toBe(mockSafeHtml);
    });

    it('should return undefined when subIcon is empty', () => {
      // Arrange
      spectator.setInput('appearance', EmptyStateAppearance.NoResults);

      // Act
      const result = spectator.component.sanitizedSubIcon();

      // Assert
      expect(result).toBeUndefined();
    });
  });

  describe('component integration', () => {
    it('should update computed properties when appearance changes', () => {
      // Arrange - Start with NoResults
      expect(spectator.component.icon()).toBe(NO_RESULTS);
      expect(spectator.component.subIcon()).toBe('');

      // Act - Change to AllDone
      spectator.setInput('appearance', EmptyStateAppearance.AllDone);

      // Assert - Properties should update
      expect(spectator.component.icon()).toBe(ALL_DONE_CUP);
      expect(spectator.component.subIcon()).toBe(ALL_DONE_FUME);
    });
  });
});
