import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ThemeProvider } from '../../theme';

// next-intl echoes keys so we assert on the label key each state maps to. `VerificationPanel`
// (rendered inside the explainer dialog) also needs `t.has` + `useLocale`.
jest.mock('next-intl', () => ({
  useTranslations: () => {
    const t = (key: string) => key;
    t.has = () => true;
    return t;
  },
  useLocale: () => 'en',
}));

const useNurseTrustBadgeMock = jest.fn();
jest.mock('@/services/verification', () => ({
  useNurseTrustBadge: (nurseId: number | undefined) => useNurseTrustBadgeMock(nurseId),
}));

import TrustBadge from './TrustBadge';
import type { BadgeState } from '@/services/verification/types';

function renderBadge(state: BadgeState, nurseId?: number) {
  return render(
    <ThemeProvider>
      <TrustBadge state={state} nurseId={nurseId} />
    </ThemeProvider>,
  );
}

describe('<TrustBadge/> component', () => {
  beforeEach(() => {
    useNurseTrustBadgeMock.mockReturnValue({ data: undefined, isLoading: false, isError: false });
  });

  it('renders the verified label + a data attribute for the verified state', () => {
    const { container } = renderBadge('verified');
    expect(screen.getByText('badge_verified')).toBeInTheDocument();
    expect(container.querySelector('[data-badge-state="verified"]')).toBeInTheDocument();
  });

  it('renders the unverified state distinctly (neutral, not alarming)', () => {
    const { container } = renderBadge('unverified');
    expect(screen.getByText('badge_unverified')).toBeInTheDocument();
    expect(container.querySelector('[data-badge-state="unverified"]')).toBeInTheDocument();
  });

  it('renders expired as its own state, distinct from unverified', () => {
    const { container } = renderBadge('expired');
    expect(screen.getByText('badge_expired')).toBeInTheDocument();
    expect(container.querySelector('[data-badge-state="expired"]')).toBeInTheDocument();
  });

  it('is not clickable by default (no nurseId), and calls no query hook at all', () => {
    const { container } = renderBadge('verified');
    expect(container.querySelector('[data-trust-explainer]')).not.toBeInTheDocument();
    // The default (non-interactive) mode never mounts the query — no QueryClientProvider needed.
    expect(useNurseTrustBadgeMock).not.toHaveBeenCalled();
  });

  it('opens the explainer dialog on tap when a nurseId is provided, fetching the badge lazily', async () => {
    useNurseTrustBadgeMock.mockReturnValue({
      data: { nurseId: 7, isVerified: true, approvedAt: '2026-01-01T00:00:00Z', credentialTypes: ['ino_membership'] },
      isLoading: false,
      isError: false,
    });
    const user = userEvent.setup();
    renderBadge('verified', 7);
    // Disabled (undefined) until opened.
    expect(useNurseTrustBadgeMock).toHaveBeenLastCalledWith(undefined);

    await user.click(screen.getByText('badge_verified'));
    expect(screen.getByText('explainer_title')).toBeInTheDocument();
    expect(useNurseTrustBadgeMock).toHaveBeenLastCalledWith(7);

    await user.click(screen.getByLabelText('explainer_close'));
    // MUI's Dialog exit transition removes the node asynchronously.
    await waitFor(() => expect(screen.queryByText('explainer_title')).not.toBeInTheDocument());
  });
});
