import { TestBed } from '@angular/core/testing';
import { Title } from '@angular/platform-browser';
import { RouterStateSnapshot } from '@angular/router';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { signal } from '@angular/core';
import { IsaTitleStrategy } from './isa-title.strategy';
import { TabService } from '@isa/core/tabs';
import { TITLE_PREFIX } from './title-prefix';

describe('IsaTitleStrategy', () => {
  let strategy: IsaTitleStrategy;
  let titleServiceMock: { setTitle: ReturnType<typeof vi.fn>; getTitle: ReturnType<typeof vi.fn> };
  let tabServiceMock: {
    activatedTabId: ReturnType<typeof signal<number | null>>;
    patchTab: ReturnType<typeof vi.fn>;
  };

  beforeEach(() => {
    // Arrange - Create mocks
    titleServiceMock = {
      setTitle: vi.fn(),
      getTitle: vi.fn().mockReturnValue(''),
    };

    tabServiceMock = {
      activatedTabId: signal<number | null>(123),
      patchTab: vi.fn(),
    };

    TestBed.configureTestingModule({
      providers: [
        IsaTitleStrategy,
        { provide: Title, useValue: titleServiceMock },
        { provide: TITLE_PREFIX, useValue: 'ISA' },
        { provide: TabService, useValue: tabServiceMock },
      ],
    });

    strategy = TestBed.inject(IsaTitleStrategy);
  });

  it('should be created', () => {
    expect(strategy).toBeTruthy();
  });

  describe('updateTitle', () => {
    it('should set document title with ISA prefix', () => {
      // Arrange
      const mockSnapshot = {
        url: '/dashboard',
      } as RouterStateSnapshot;

      // Mock buildTitle to return a specific title
      vi.spyOn(strategy, 'buildTitle').mockReturnValue('Dashboard');

      // Act
      strategy.updateTitle(mockSnapshot);

      // Assert
      expect(titleServiceMock.setTitle).toHaveBeenCalledWith('ISA - Dashboard');
    });

    it('should update tab name via TabService', () => {
      // Arrange
      const mockSnapshot = {
        url: '/search',
      } as RouterStateSnapshot;

      vi.spyOn(strategy, 'buildTitle').mockReturnValue('Artikelsuche');

      // Act
      strategy.updateTitle(mockSnapshot);

      // Assert
      expect(tabServiceMock.patchTab).toHaveBeenCalledWith(123, {
        name: 'Artikelsuche',
      });
    });

    it('should use custom prefix from TITLE_PREFIX', () => {
      // Arrange - Reset TestBed and configure with custom TITLE_PREFIX
      TestBed.resetTestingModule();
      TestBed.configureTestingModule({
        providers: [
          IsaTitleStrategy,
          { provide: Title, useValue: titleServiceMock },
          { provide: TITLE_PREFIX, useValue: 'MyApp' }, // Custom prefix
          { provide: TabService, useValue: tabServiceMock },
        ],
      });

      const customStrategy = TestBed.inject(IsaTitleStrategy);

      const mockSnapshot = {
        url: '/settings',
      } as RouterStateSnapshot;

      vi.spyOn(customStrategy, 'buildTitle').mockReturnValue('Settings');

      // Act
      customStrategy.updateTitle(mockSnapshot);

      // Assert
      expect(titleServiceMock.setTitle).toHaveBeenCalledWith('MyApp - Settings');
    });

    it('should not update tab when activatedTabId is null', () => {
      // Arrange
      tabServiceMock.activatedTabId.set(null);

      const mockSnapshot = {
        url: '/dashboard',
      } as RouterStateSnapshot;

      vi.spyOn(strategy, 'buildTitle').mockReturnValue('Dashboard');

      // Act
      strategy.updateTitle(mockSnapshot);

      // Assert
      expect(titleServiceMock.setTitle).toHaveBeenCalledWith('ISA - Dashboard');
      expect(tabServiceMock.patchTab).not.toHaveBeenCalled();
    });

    it('should not update anything when buildTitle returns empty string', () => {
      // Arrange
      const mockSnapshot = {
        url: '/no-title',
      } as RouterStateSnapshot;

      vi.spyOn(strategy, 'buildTitle').mockReturnValue('');

      // Act
      strategy.updateTitle(mockSnapshot);

      // Assert
      expect(titleServiceMock.setTitle).not.toHaveBeenCalled();
      expect(tabServiceMock.patchTab).not.toHaveBeenCalled();
    });

    it('should not update anything when buildTitle returns undefined', () => {
      // Arrange
      const mockSnapshot = {
        url: '/no-title',
      } as RouterStateSnapshot;

      vi.spyOn(strategy, 'buildTitle').mockReturnValue(undefined as any);

      // Act
      strategy.updateTitle(mockSnapshot);

      // Assert
      expect(titleServiceMock.setTitle).not.toHaveBeenCalled();
      expect(tabServiceMock.patchTab).not.toHaveBeenCalled();
    });
  });
});
