import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi, beforeEach } from 'vitest';

const mockUsePage = vi.hoisted(() => vi.fn());

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    usePage: mockUsePage,
    router: {
      post: vi.fn(),
      get: vi.fn(),
      on: vi.fn(() => vi.fn()),
    },
    Link: ({ children, href }: { children: React.ReactNode; href: string }) => (
      <a href={href}>{children}</a>
    ),
  };
});

import { router } from '@inertiajs/react';

import { ImpersonationBanner } from './ImpersonationBanner';

const makeImpersonatingProps = (overrides = {}) => ({
  props: {
    auth: {
      impersonating: true,
      user: {
        id: 42,
        name: 'Alice Example',
        email: 'alice@example.com',
        is_admin: false,
      },
    },
    features: { billing: false, socialAuth: false, emailVerification: false, apiTokens: false, userSettings: false, notifications: false, onboarding: false, apiDocs: false, twoFactor: false, webhooks: false, admin: true },
    flash: {},
    errors: {},
    notifications_unread_count: 0,
    sites: [],
    limits: null,
    active_jobs: [],
    ai_max_batch_size: 10,
    ai_defaults: { temperature: 0.7, model: 'gpt-4' },
    polling_interval_ms: 5000,
    ...overrides,
  },
});

describe('ImpersonationBanner', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders nothing when not impersonating', () => {
    mockUsePage.mockReturnValue({
      props: { auth: { impersonating: false, user: null }, features: {}, flash: {}, errors: {}, notifications_unread_count: 0, sites: [], limits: null, active_jobs: [], ai_max_batch_size: 10, ai_defaults: {}, polling_interval_ms: 5000 },
    });
    const { container } = render(<ImpersonationBanner />);
    expect(container).toBeEmptyDOMElement();
  });

  it('renders banner when impersonating', () => {
    mockUsePage.mockReturnValue(makeImpersonatingProps());
    render(<ImpersonationBanner />);
    expect(screen.getByText(/you are impersonating/i)).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /stop impersonating/i })).toBeInTheDocument();
  });

  it('does not fire router.post immediately on Stop Impersonating click — opens dialog first', async () => {
    const user = userEvent.setup();
    mockUsePage.mockReturnValue(makeImpersonatingProps());
    render(<ImpersonationBanner />);
    await user.click(screen.getByRole('button', { name: /stop impersonating/i }));
    expect(router.post).not.toHaveBeenCalled();
    expect(screen.getByRole('alertdialog')).toBeInTheDocument();
    // Dialog description should include the target user name
    expect(screen.getByText(/end the session as Alice Example/i)).toBeInTheDocument();
  });

  it('fires router.post when confirm is clicked', async () => {
    const user = userEvent.setup();
    mockUsePage.mockReturnValue(makeImpersonatingProps());
    render(<ImpersonationBanner />);
    await user.click(screen.getByRole('button', { name: /stop impersonating/i }));
    await user.click(screen.getByRole('button', { name: /^stop impersonating$/i }));
    expect(router.post).toHaveBeenCalledTimes(1);
    expect(router.post).toHaveBeenCalledWith(
      '/admin/impersonate/stop',
      {},
      expect.any(Object),
    );
  });

  it('does not fire router.post when cancel is clicked', async () => {
    const user = userEvent.setup();
    mockUsePage.mockReturnValue(makeImpersonatingProps());
    render(<ImpersonationBanner />);
    await user.click(screen.getByRole('button', { name: /stop impersonating/i }));
    await user.click(screen.getByRole('button', { name: /cancel/i }));
    expect(router.post).not.toHaveBeenCalled();
  });
});
