import { provideHttpClient } from '@angular/common/http';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import {
  AUTH_BFF_BASE_URL,
  AUTH_NAVIGATOR,
  AUTH_PATH_PREFIX,
  type CurrentUser,
} from 'feature-auth';
import { AdminHeader } from './header';

const BFF_BASE = 'http://bff.test/api';
const ADMIN_ME_URL = `${BFF_BASE}/admin/auth/me`;

const USER: CurrentUser = {
  oid: 'admin-oid',
  tid: 'tenant-1',
  username: 'admin@apf.example',
  displayName: 'Admin Smith',
};

async function setup(opts: { onBootstrap: 'authenticated' | 'anonymous' | 'leave' }) {
  const navigate = vi.fn();
  TestBed.configureTestingModule({
    imports: [AdminHeader],
    providers: [
      provideRouter([]),
      provideHttpClient(),
      provideHttpClientTesting(),
      { provide: AUTH_BFF_BASE_URL, useValue: BFF_BASE },
      { provide: AUTH_PATH_PREFIX, useValue: '/admin/auth' },
      { provide: AUTH_NAVIGATOR, useValue: navigate },
    ],
  });
  const fixture = TestBed.createComponent(AdminHeader);
  const http = TestBed.inject(HttpTestingController);
  // AuthService fires the bootstrap /me from its constructor. Flush
  // it before the first whenStable so the signal update has settled
  // by the time we assert on the rendered DOM. `leave` keeps the
  // loading state visible for tests that need it.
  if (opts.onBootstrap !== 'leave') {
    const req = http.expectOne(ADMIN_ME_URL);
    if (opts.onBootstrap === 'authenticated') {
      req.flush(USER);
    } else {
      req.flush({}, { status: 401, statusText: 'Unauthorized' });
    }
    await Promise.resolve();
  }
  fixture.detectChanges();
  await fixture.whenStable();
  return { fixture, http, navigate };
}

describe('AdminHeader', () => {
  it('renders the wordmark + admin badge', async () => {
    const { fixture } = await setup({ onBootstrap: 'anonymous' });
    const root = fixture.nativeElement as HTMLElement;
    expect(root.querySelector('.brand-wordmark')?.textContent).toContain('APF Portal');
    expect(root.querySelector('.brand-badge')?.textContent?.trim()).toBe('Admin');
  });

  it('shows a Sign in button when anonymous', async () => {
    const { fixture } = await setup({ onBootstrap: 'anonymous' });
    const button = (fixture.nativeElement as HTMLElement).querySelector('.btn--primary');
    expect(button?.textContent?.trim()).toBe('Sign in');
  });

  it('shows the user menu trigger with initials when authenticated', async () => {
    const { fixture } = await setup({ onBootstrap: 'authenticated' });
    const root = fixture.nativeElement as HTMLElement;
    const menu = root.querySelector('[data-testid="user-menu"]');
    expect(menu).not.toBeNull();
    expect(menu?.querySelector('.user-menu__avatar')?.textContent?.trim()).toBe('AS');
  });

  it('opens the menu and exposes displayName + Sign out inside the panel', async () => {
    const { fixture } = await setup({ onBootstrap: 'authenticated' });
    const trigger = (fixture.nativeElement as HTMLElement).querySelector<HTMLButtonElement>(
      '[data-testid="user-menu"] button[aria-haspopup="menu"]',
    );
    trigger?.click();
    fixture.detectChanges();
    await fixture.whenStable();
    const panel = document.body.querySelector('.user-menu__panel');
    expect(panel).not.toBeNull();
    expect(panel?.querySelector('.user-menu__header-name')?.textContent).toContain('Admin Smith');
    expect(panel?.querySelector('.user-menu__item--sign-out')).not.toBeNull();
  });

  it('navigates to the admin login URL on Sign in click', async () => {
    const { fixture, navigate } = await setup({ onBootstrap: 'anonymous' });
    (fixture.nativeElement as HTMLElement)
      .querySelector<HTMLButtonElement>('.btn--primary')
      ?.click();
    expect(navigate).toHaveBeenCalledWith(`${BFF_BASE}/admin/auth/login`);
  });

  it('navigates to the admin logout URL on Sign out click inside the menu panel', async () => {
    const { fixture, navigate } = await setup({ onBootstrap: 'authenticated' });
    const trigger = (fixture.nativeElement as HTMLElement).querySelector<HTMLButtonElement>(
      '[data-testid="user-menu"] button[aria-haspopup="menu"]',
    );
    trigger?.click();
    fixture.detectChanges();
    await fixture.whenStable();
    document.body.querySelector<HTMLButtonElement>('.user-menu__item--sign-out')?.click();
    expect(navigate).toHaveBeenCalledWith(`${BFF_BASE}/admin/auth/logout`);
  });
});
