import { Component } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { IfRoleDirective } from './if-role.directive';
import { RoleService } from './role.service';
import { Role } from './role';

@Component({
  standalone: true,
  imports: [IfRoleDirective],
  template: `
    <div *ifRole="role" data-test="content">Store Content</div>
  `,
})
class TestIfRoleComponent {
  role = Role.Store;
}

@Component({
  standalone: true,
  imports: [IfRoleDirective],
  template: `
    <div *ifRole="role; else noAccess" data-test="content">Store Content</div>
    <ng-template #noAccess>
      <div data-test="else">No Access</div>
    </ng-template>
  `,
})
class TestIfRoleElseComponent {
  role = Role.Store;
}

@Component({
  standalone: true,
  imports: [IfRoleDirective],
  template: `
    <div *ifNotRole="role" data-test="content">Non-Store Content</div>
  `,
})
class TestIfNotRoleComponent {
  role = Role.Store;
}

describe('IfRoleDirective', () => {
  let roleService: { hasRole: ReturnType<typeof vi.fn> };

  beforeEach(() => {
    roleService = {
      hasRole: vi.fn(),
    };

    TestBed.configureTestingModule({
      providers: [{ provide: RoleService, useValue: roleService }],
    });
  });

  describe('ifRole', () => {
    it('should render content when user has role', () => {
      roleService.hasRole.mockReturnValue(true);

      const fixture = TestBed.createComponent(TestIfRoleComponent);
      fixture.detectChanges();

      const content = fixture.nativeElement.querySelector('[data-test="content"]');
      expect(content).toBeTruthy();
      expect(content?.textContent).toContain('Store Content');
    });

    it('should not render content when user does not have role', () => {
      roleService.hasRole.mockReturnValue(false);

      const fixture = TestBed.createComponent(TestIfRoleComponent);
      fixture.detectChanges();

      const content = fixture.nativeElement.querySelector('[data-test="content"]');
      expect(content).toBeFalsy();
    });

    it('should render else template when user does not have role', () => {
      roleService.hasRole.mockReturnValue(false);

      const fixture = TestBed.createComponent(TestIfRoleElseComponent);
      fixture.detectChanges();

      const content = fixture.nativeElement.querySelector('[data-test="content"]');
      const elseContent = fixture.nativeElement.querySelector('[data-test="else"]');

      expect(content).toBeFalsy();
      expect(elseContent).toBeTruthy();
      expect(elseContent?.textContent).toContain('No Access');
    });

    it('should update when role input changes', () => {
      roleService.hasRole.mockReturnValue(true);

      const fixture = TestBed.createComponent(TestIfRoleComponent);
      fixture.detectChanges();

      let content = fixture.nativeElement.querySelector('[data-test="content"]');
      expect(content).toBeTruthy();

      // Change role and mock to return false
      roleService.hasRole.mockReturnValue(false);
      fixture.componentInstance.role = Role.CallCenter;
      fixture.detectChanges();

      content = fixture.nativeElement.querySelector('[data-test="content"]');
      expect(content).toBeFalsy();
    });
  });

  describe('ifNotRole', () => {
    it('should render content when user does NOT have role', () => {
      roleService.hasRole.mockReturnValue(false);

      const fixture = TestBed.createComponent(TestIfNotRoleComponent);
      fixture.detectChanges();

      const content = fixture.nativeElement.querySelector('[data-test="content"]');
      expect(content).toBeTruthy();
      expect(content?.textContent).toContain('Non-Store Content');
    });

    it('should not render content when user has role', () => {
      roleService.hasRole.mockReturnValue(true);

      const fixture = TestBed.createComponent(TestIfNotRoleComponent);
      fixture.detectChanges();

      const content = fixture.nativeElement.querySelector('[data-test="content"]');
      expect(content).toBeFalsy();
    });
  });

  describe('multiple roles', () => {
    it('should handle array of roles', () => {
      roleService.hasRole.mockReturnValue(true);

      @Component({
        standalone: true,
        imports: [IfRoleDirective],
        template: `<div *ifRole="roles" data-test="content">Content</div>`,
      })
      class TestMultipleRolesComponent {
        roles = [Role.Store, Role.CallCenter];
      }

      const fixture = TestBed.createComponent(TestMultipleRolesComponent);
      fixture.detectChanges();

      expect(roleService.hasRole).toHaveBeenCalledWith([Role.Store, Role.CallCenter]);

      const content = fixture.nativeElement.querySelector('[data-test="content"]');
      expect(content).toBeTruthy();
    });
  });
});
