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

const mocks = vi.hoisted(() => ({
  post: vi.fn(),
  reset: vi.fn(),
  setData: vi.fn(),
  useForm: vi.fn(() => ({
    data: { email: '', name: '' },
    setData: vi.fn(),
    post: vi.fn(),
    processing: false,
    errors: {} as Record<string, string>,
    wasSuccessful: false,
    reset: vi.fn(),
  })),
}));

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  const { createElement } = await import('react');
  return {
    ...actual,
    Head: () => null,
    Link: ({
      href,
      children,
      className,
      ...rest
    }: {
      href: string;
      children: unknown;
      className?: string;
      [key: string]: unknown;
    }) =>
      createElement(
        'a',
        { href, className, ...rest },
        children as Parameters<typeof createElement>[2],
      ),
    router: {
      visit: vi.fn(),
      post: vi.fn(),
      get: vi.fn(),
      put: vi.fn(),
      patch: vi.fn(),
      delete: vi.fn(),
      reload: vi.fn(),
      on: vi.fn(() => vi.fn()),
    },
    usePage: vi.fn(() => ({
      props: {
        auth: { user: null },
        errors: {},
        flash: {},
        polling_interval_ms: 5000,
      },
    })),
    useForm: mocks.useForm,
  };
});

import { NewsletterSignup } from '@/Components/marketing/NewsletterSignup';

beforeEach(() => {
  vi.clearAllMocks();
  mocks.useForm.mockReturnValue({
    data: { email: '', name: '' },
    setData: vi.fn(),
    post: mocks.post,
    processing: false,
    errors: {} as Record<string, string>,
    wasSuccessful: false,
    reset: mocks.reset,
  });
});

describe('NewsletterSignup', () => {
  it('renders email input and subscribe button in default variant', () => {
    render(<NewsletterSignup />);

    expect(screen.getByLabelText(/email address/i)).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /subscribe for free/i })).toBeInTheDocument();
  });

  it('renders name input in default variant', () => {
    render(<NewsletterSignup />);

    expect(screen.getByLabelText(/name/i)).toBeInTheDocument();
  });

  it('renders compact variant with single-row layout', () => {
    render(<NewsletterSignup compact />);

    expect(screen.getByPlaceholderText(/you@example.com/i)).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /subscribe/i })).toBeInTheDocument();
    // compact variant has no heading
    expect(screen.queryByRole('heading')).not.toBeInTheDocument();
  });

  it('shows success state when wasSuccessful is true', () => {
    mocks.useForm.mockReturnValue({
      data: { email: '', name: '' },
      setData: vi.fn(),
      post: mocks.post,
      processing: false,
      errors: {},
      wasSuccessful: true,
      reset: mocks.reset,
    });

    render(<NewsletterSignup />);

    expect(screen.getByText(/you're subscribed/i)).toBeInTheDocument();
    expect(screen.queryByRole('button', { name: /subscribe/i })).not.toBeInTheDocument();
  });

  it('shows error message when errors.email is set', () => {
    mocks.useForm.mockReturnValue({
      data: { email: '', name: '' },
      setData: vi.fn(),
      post: mocks.post,
      processing: false,
      errors: { email: 'The email field is required.' },
      wasSuccessful: false,
      reset: mocks.reset,
    });

    render(<NewsletterSignup />);

    expect(screen.getByText(/the email field is required/i)).toBeInTheDocument();
  });

  it('calls form post on submission', () => {
    render(<NewsletterSignup />);

    const form = screen.getByRole('form', { name: /newsletter signup/i });
    fireEvent.submit(form);

    expect(mocks.post).toHaveBeenCalledOnce();
  });
});
