/**
 * AppHeader.test.tsx
 * Unit tests for the AppHeader component
 * Covers: page titles, navigation links, active state, scoring card,
 * logout button, mobile hamburger menu toggle, and accessibility.
 */

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { vi } from 'vitest';
import AppHeader from '../../src/components/AppHeader';

const mockOnLogout = vi.fn();

const renderAppHeader = (props: React.ComponentProps<typeof AppHeader>) => {
  return render(
    <BrowserRouter>
      <AppHeader {...props} />
    </BrowserRouter>
  );
};

describe('AppHeader Component', () => {
  beforeEach(() => {
    mockOnLogout.mockClear();
  });

  it('should render dashboard page title and icon', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    // Find the h1 element which contains the page title
    const heading = screen.getByRole('heading', { name: /dashboard/i });
    expect(heading).toBeInTheDocument();
  });

  it('should render quests page title and icon', () => {
    renderAppHeader({
      page: 'quests',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const heading = screen.getByRole('heading', { name: /quests/i });
    expect(heading).toBeInTheDocument();
  });

  it('should render map page title and icon', () => {
    renderAppHeader({
      page: 'map',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const heading = screen.getByRole('heading', { name: /middle-earth map/i });
    expect(heading).toBeInTheDocument();
  });

  it('should render inventory page title and icon', () => {
    renderAppHeader({
      page: 'inventory',
      gold: 100,
      completedQuests: 5,
      averageSavings: 15.5,
      onLogout: mockOnLogout,
    });

    const heading = screen.getByRole('heading', { name: /inventory/i });
    expect(heading).toBeInTheDocument();
  });

  it('should render navigation links', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    expect(screen.getByTestId('header-nav-dashboard')).toBeInTheDocument();
    expect(screen.getByTestId('header-nav-quests')).toBeInTheDocument();
    expect(screen.getByTestId('header-nav-map')).toBeInTheDocument();
    expect(screen.getByTestId('header-nav-inventory')).toBeInTheDocument();
  });

  it('should render logout button', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const logoutButton = screen.getByTestId('header-logout-button');
    expect(logoutButton).toBeInTheDocument();
    expect(logoutButton).toHaveTextContent('Leave Fellowship');
  });

  it('should highlight current page link', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const dashboardLink = screen.getByTestId('header-nav-dashboard');
    // The dashboard link should have different styling when active
    expect(dashboardLink).toHaveClass('font-bold', 'text-gold');
  });

  it('should render ScoringCard with correct props', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 500,
      completedQuests: 10,
      averageSavings: 20.5,
      onLogout: mockOnLogout,
    });

    // Check that ScoringCard is rendered with correct values
    expect(screen.getByTestId('scoring-card')).toBeInTheDocument();
    expect(screen.getByTestId('scoring-card-gold')).toHaveTextContent('500');
    expect(screen.getByTestId('scoring-card-quests')).toHaveTextContent('10');
    expect(screen.getByTestId('scoring-card-savings')).toHaveTextContent('20.50%');
  });

  it('should render ScoringCard without average savings on non-inventory pages', () => {
    renderAppHeader({
      page: 'quests',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    expect(screen.getByTestId('scoring-card-savings')).toHaveTextContent('—');
  });

  it('should have navigation element with correct testId', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    expect(screen.getByTestId('header-navigation')).toBeInTheDocument();
  });

  it('should render different page titles for different pages', () => {
    const { rerender } = render(
      <BrowserRouter>
        <AppHeader
          page="dashboard"
          gold={100}
          completedQuests={5}
          averageSavings={undefined}
          onLogout={mockOnLogout}
        />
      </BrowserRouter>
    );

    let heading = screen.getByRole('heading', { name: /dashboard/i });
    expect(heading).toBeInTheDocument();

    rerender(
      <BrowserRouter>
        <AppHeader
          page="inventory"
          gold={100}
          completedQuests={5}
          averageSavings={15.5}
          onLogout={mockOnLogout}
        />
      </BrowserRouter>
    );

    heading = screen.getByRole('heading', { name: /inventory/i });
    expect(heading).toBeInTheDocument();
  });

  // ── Mobile Hamburger Menu ──────────────────────────────────────────────────

  it('should render the mobile hamburger button', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const hamburger = screen.getByTestId('header-mobile-menu-btn');
    expect(hamburger).toBeInTheDocument();
    expect(hamburger).toHaveAttribute('aria-expanded', 'false');
  });

  it('should toggle aria-expanded on hamburger click', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const hamburger = screen.getByTestId('header-mobile-menu-btn');

    // Initially closed
    expect(hamburger).toHaveAttribute('aria-expanded', 'false');

    // Open
    fireEvent.click(hamburger);
    expect(hamburger).toHaveAttribute('aria-expanded', 'true');

    // Close again
    fireEvent.click(hamburger);
    expect(hamburger).toHaveAttribute('aria-expanded', 'false');
  });

  it('should add lotr-hamburger--open class when menu is open', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const hamburger = screen.getByTestId('header-mobile-menu-btn');
    expect(hamburger).not.toHaveClass('lotr-hamburger--open');

    fireEvent.click(hamburger);
    expect(hamburger).toHaveClass('lotr-hamburger--open');
  });

  it('should apply lotr-header--menu-open class to header when hamburger is open', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const hamburger = screen.getByTestId('header-mobile-menu-btn');
    const header = screen.getByRole('banner');

    expect(header).not.toHaveClass('lotr-header--menu-open');

    fireEvent.click(hamburger);
    expect(header).toHaveClass('lotr-header--menu-open');
  });

  it('should close mobile menu when a nav link is clicked', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const hamburger = screen.getByTestId('header-mobile-menu-btn');
    fireEvent.click(hamburger);
    expect(hamburger).toHaveAttribute('aria-expanded', 'true');

    // Click a nav link → should close the menu
    const questsLink = screen.getByTestId('header-nav-quests');
    fireEvent.click(questsLink);
    expect(hamburger).toHaveAttribute('aria-expanded', 'false');
  });

  // ── Fantasy Branding ──────────────────────────────────────────────────────

  it('should render the brand ring icon SVG', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    // The ring SVG is inside the header
    const header = screen.getByRole('banner');
    const rings = header.querySelectorAll('svg');
    // At minimum two SVGs: ring icon + elvish border
    expect(rings.length).toBeGreaterThanOrEqual(2);
  });

  it('should have aria-label on the hamburger for accessibility', () => {
    renderAppHeader({
      page: 'dashboard',
      gold: 100,
      completedQuests: 5,
      averageSavings: undefined,
      onLogout: mockOnLogout,
    });

    const hamburger = screen.getByTestId('header-mobile-menu-btn');
    expect(hamburger).toHaveAttribute('aria-label', 'Open navigation menu');

    fireEvent.click(hamburger);
    expect(hamburger).toHaveAttribute('aria-label', 'Close navigation menu');
  });
});
