import { App as AntApp, ConfigProvider } from 'antd';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter, Route, Routes, useLocation } from 'react-router-dom';
import { describe, expect, it, vi } from 'vitest';

import { AppContext } from '../../src/frontend/app-context';
import { I18nProvider } from '../../src/frontend/i18n/react';
import { mailhubTheme } from '../../src/frontend/theme';
import { AdminLayout, navigationSelection, visibleNavigation } from '../../src/layouts/AdminLayout';
import type { AppContextValue } from '../../src/frontend/app-context';

describe('AdminLayout navigation', () => {
  it('hides all system management destinations from a normal user', () => {
    const paths = visibleNavigation(false).flatMap((group) => group.items.map((item) => item.path));
    expect(paths).not.toContain('/admin/users');
    expect(paths).not.toContain('/settings');
  });

  it('maps detail routes back to their owning navigation item', () => {
    expect(navigationSelection('/activity/42')).toBe('/activity');
    expect(navigationSelection('/domains/7/dns')).toBe('/domains');
    expect(navigationSelection('/inbox/messages/9')).toBe('/inbox');
  });

  it('navigates with semantic menu items and exposes a skip link', async () => {
    const user = userEvent.setup();
    renderShell('/overview', { role: 'admin' });

    expect(screen.getByRole('link', { name: '跳至主要内容' }).getAttribute('href')).toBe('#main-content');
    const activityItems = screen.getAllByText('发送活动');
    await user.click(activityItems[0]);
    expect(screen.getByTestId('location').textContent).toBe('/activity');
  });

  it('provides an explicit mobile navigation escape action', async () => {
    const user = userEvent.setup();
    renderShell('/overview', { role: 'user' });

    await user.click(screen.getByRole('button', { name: '打开主导航' }));
    const close = await screen.findByRole('button', { name: '关闭主导航' });
    expect(close.style.minHeight).toBe('44px');
    expect(close.style.minWidth).toBe('44px');
    await user.click(close);
    await waitFor(() => expect(screen.queryByRole('button', { name: '关闭主导航' })).toBeNull());
  });

  it('keeps mobile navigation available between Ant Design lg and the 1024px product breakpoint', async () => {
    vi.spyOn(window, 'matchMedia').mockImplementation((query) => mediaQueryList(query === '(min-width: 992px)', query));
    const user = userEvent.setup();
    renderShell('/overview', { role: 'user' });

    await user.click(screen.getByRole('button', { name: '打开主导航' }));

    expect(await screen.findByRole('button', { name: '关闭主导航' })).toBeTruthy();
  });
});

function mediaQueryList(matches: boolean, media: string): MediaQueryList {
  return {
    matches,
    media,
    onchange: null,
    addListener: () => undefined,
    removeListener: () => undefined,
    addEventListener: () => undefined,
    removeEventListener: () => undefined,
    dispatchEvent: () => false
  };
}

function renderShell(path: string, { role }: { role: 'admin' | 'user' }) {
  const context: AppContextValue = {
    user: {
      id: 1,
      username: 'operator',
      email: 'operator@example.test',
      role,
      status: 'active'
    },
    config: {
      appBaseUrl: 'https://mail.example.test',
      mailHostname: 'mail.example.test',
      sendingIp: '192.0.2.10',
      defaultSpfMechanisms: '',
      dmarcPolicy: 'none',
      dmarcRua: '',
      sendRequiresVerified: true,
      engagementTrackingEnabled: true,
      listUnsubscribeMailto: '',
      listUnsubscribeUrl: '',
      listUnsubscribePostEnabled: false,
      feedbackIdEnabled: false,
      reportAbuseTo: '',
      csaComplaintsTo: '',
      bounceAddress: '',
      bounceEnvelopeEnabled: false
    },
    refreshBootstrap: vi.fn(async () => undefined),
    logout: vi.fn(async () => undefined)
  };

  return render(
    <ConfigProvider theme={mailhubTheme}>
      <AntApp>
        <I18nProvider>
          <AppContext.Provider value={context}>
            <MemoryRouter initialEntries={[path]}>
              <Routes>
                <Route element={<AdminLayout />}>
                  <Route path="*" element={<LocationProbe />} />
                </Route>
              </Routes>
            </MemoryRouter>
          </AppContext.Provider>
        </I18nProvider>
      </AntApp>
    </ConfigProvider>
  );
}

function LocationProbe() {
  const location = useLocation();
  return <div data-testid="location">{location.pathname}</div>;
}
