/** @vitest-environment jsdom */
import { describe, it, expect, vi, afterEach } from 'vitest';
import { render, screen, cleanup, fireEvent, waitFor } from '@testing-library/react';
import { LeadGateView } from './LeadGateView';
import { en } from '../i18n/en';

afterEach(cleanup);

function renderGate(onSubmit = vi.fn().mockResolvedValue(true), onSkip = vi.fn()) {
  render(<LeadGateView onSubmit={onSubmit} onSkip={onSkip} t={en.lead} />);
  return {
    onSubmit,
    onSkip,
    email: screen.getByLabelText(en.lead.emailLabel) as HTMLInputElement,
    consent: screen.getByRole('checkbox') as HTMLInputElement,
    submit: screen.getByRole('button', { name: en.lead.submit }) as HTMLButtonElement,
  };
}

describe('what the visitor is told', () => {
  it('states the purpose before asking for anything', () => {
    renderGate();
    expect(screen.getByText(en.lead.purpose)).toBeDefined();
  });

  // Consent that arrives pre-ticked is not consent.
  it('leaves the consent box unticked', () => {
    const { consent } = renderGate();
    expect(consent.checked).toBe(false);
  });
});

describe('what it takes to submit', () => {
  it('refuses until both the address and the consent are there', () => {
    const { email, consent, submit } = renderGate();
    expect(submit.disabled).toBe(true);

    fireEvent.change(email, { target: { value: 'buyer@store.co' } });
    expect(submit.disabled).toBe(true);

    fireEvent.click(consent);
    expect(submit.disabled).toBe(false);
  });

  it('refuses a malformed address even with the consent ticked', () => {
    const { email, consent, submit } = renderGate();
    fireEvent.change(email, { target: { value: 'buyer@store' } });
    fireEvent.click(consent);
    expect(submit.disabled).toBe(true);
  });

  it('hands the trimmed address to the parent', async () => {
    const { email, consent, submit, onSubmit } = renderGate();
    fireEvent.change(email, { target: { value: '  buyer@store.co  ' } });
    fireEvent.click(consent);
    fireEvent.click(submit);

    await waitFor(() => expect(onSubmit).toHaveBeenCalledWith('buyer@store.co'));
  });
});

describe('when saving fails', () => {
  it('says so and lets the visitor try again', async () => {
    const onSubmit = vi.fn().mockResolvedValue(false);
    const { email, consent, submit } = renderGate(onSubmit);
    fireEvent.change(email, { target: { value: 'buyer@store.co' } });
    fireEvent.click(consent);
    fireEvent.click(submit);

    await waitFor(() => expect(screen.getByRole('alert').textContent).toBe(en.lead.error));
    expect((screen.getByRole('button', { name: en.lead.submit }) as HTMLButtonElement).disabled).toBe(
      false
    );
  });
});

describe('the way out', () => {
  it('is a plain button that needs no email at all', () => {
    const { onSkip } = renderGate();
    fireEvent.click(screen.getByRole('button', { name: en.lead.skip }));
    expect(onSkip).toHaveBeenCalledTimes(1);
  });
});
