import { render, screen, fireEvent } from '@testing-library/react';
import { ThemeProvider } from '../../theme';
import ConfirmDialog from './ConfirmDialog';

describe('<ConfirmDialog/>', () => {
  const wrap = (ui: React.ReactNode) => render(<ThemeProvider>{ui}</ThemeProvider>);
  const base = {
    title: 'Run batch?',
    confirmLabel: 'Run',
    cancelLabel: 'Cancel',
    onClose: jest.fn(),
  };

  it('renders the title and body when open', () => {
    wrap(<ConfirmDialog open body="This moves money" onConfirm={jest.fn()} {...base} />);
    expect(screen.getByText('Run batch?')).toBeInTheDocument();
    expect(screen.getByText('This moves money')).toBeInTheDocument();
  });

  it('calls onConfirm with no reason for a plain confirm', () => {
    const onConfirm = jest.fn();
    wrap(<ConfirmDialog open onConfirm={onConfirm} {...base} />);
    fireEvent.click(screen.getByRole('button', { name: 'Run' }));
    expect(onConfirm).toHaveBeenCalledWith(undefined);
  });

  it('disables confirm until a required reason is entered, then passes it', () => {
    const onConfirm = jest.fn();
    wrap(<ConfirmDialog open requireReason reasonLabel="Reason" onConfirm={onConfirm} {...base} />);
    const confirmBtn = screen.getByRole('button', { name: 'Run' });
    expect(confirmBtn).toBeDisabled();
    fireEvent.change(screen.getByLabelText('Reason'), { target: { value: 'bad docs' } });
    expect(confirmBtn).not.toBeDisabled();
    fireEvent.click(confirmBtn);
    expect(onConfirm).toHaveBeenCalledWith('bad docs');
  });

  it('calls onClose from cancel', () => {
    const onClose = jest.fn();
    wrap(<ConfirmDialog open onConfirm={jest.fn()} {...base} onClose={onClose} />);
    fireEvent.click(screen.getByRole('button', { name: 'Cancel' }));
    expect(onClose).toHaveBeenCalledTimes(1);
  });

  it('renders the typed-confirmation field when requireTypedConfirmation is set', () => {
    wrap(
      <ConfirmDialog
        open
        onConfirm={jest.fn()}
        {...base}
        requireTypedConfirmation={['CONFIRM', '150000']}
        typedConfirmationLabel="Type to confirm"
      />,
    );
    expect(screen.getByLabelText('Type to confirm')).toBeInTheDocument();
  });

  it('keeps confirm disabled until the typed value matches, case/whitespace-insensitively', () => {
    const onConfirm = jest.fn();
    wrap(
      <ConfirmDialog
        open
        onConfirm={onConfirm}
        {...base}
        requireTypedConfirmation={['CONFIRM', '150000']}
        typedConfirmationLabel="Type to confirm"
      />,
    );
    const confirmBtn = screen.getByRole('button', { name: 'Run' });
    const field = screen.getByLabelText('Type to confirm');

    expect(confirmBtn).toBeDisabled();

    fireEvent.change(field, { target: { value: 'nope' } });
    expect(confirmBtn).toBeDisabled();

    fireEvent.change(field, { target: { value: '  confirm  ' } });
    expect(confirmBtn).not.toBeDisabled();

    fireEvent.click(confirmBtn);
    expect(onConfirm).toHaveBeenCalledWith(undefined);
  });

  it('enables confirm on an exact match against a different allowed value (e.g. an amount)', () => {
    wrap(
      <ConfirmDialog
        open
        onConfirm={jest.fn()}
        {...base}
        requireTypedConfirmation={['CONFIRM', '150000']}
        typedConfirmationLabel="Type to confirm"
      />,
    );
    const confirmBtn = screen.getByRole('button', { name: 'Run' });
    fireEvent.change(screen.getByLabelText('Type to confirm'), { target: { value: '150000' } });
    expect(confirmBtn).not.toBeDisabled();
  });
});
