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

import { type InertiaFormProps, useForm } from '@inertiajs/react';

import BundledAiConsentModal from '@/Components/BundledAiConsentModal';

const mockPost = vi.fn();
const mockedUseForm = vi.mocked(useForm);

type ConsentFormData = { consent_type: 'bundled_ai_processing' };

function mockFormReturn(
  overrides: Partial<InertiaFormProps<ConsentFormData>> = {},
): InertiaFormProps<ConsentFormData> {
  return {
    data: { consent_type: 'bundled_ai_processing' },
    isDirty: false,
    errors: {},
    hasErrors: false,
    processing: false,
    progress: null,
    wasSuccessful: false,
    recentlySuccessful: false,
    setData: vi.fn(),
    transform: vi.fn(),
    setDefaults: vi.fn() as InertiaFormProps<ConsentFormData>['setDefaults'],
    reset: vi.fn(),
    clearErrors: vi.fn(),
    resetAndClearErrors: vi.fn(),
    setError: vi.fn() as InertiaFormProps<ConsentFormData>['setError'],
    submit: vi.fn(),
    get: vi.fn(),
    post: mockPost,
    put: vi.fn(),
    patch: vi.fn(),
    delete: vi.fn(),
    cancel: vi.fn(),
    dontRemember: vi.fn() as InertiaFormProps<ConsentFormData>['dontRemember'],
    withPrecognition: vi.fn() as unknown as InertiaFormProps<ConsentFormData>['withPrecognition'],
    ...overrides,
  } as unknown as InertiaFormProps<ConsentFormData>;
}

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Link: ({ href, children, className }: { href: string; children: React.ReactNode; className?: string }) => {
      // Ensure href is a valid URL for the test environment
      const url = href.startsWith('http') ? href : `http://localhost${href}`;
      return <a href={url} className={className}>{children}</a>;
    },
    useForm: vi.fn(),
  };
});

describe('BundledAiConsentModal', () => {
  const defaultProps = {
    open: true,
    onClose: vi.fn(),
    onConsentGranted: vi.fn(),
  };

  beforeEach(() => {
    vi.clearAllMocks();
    vi.stubGlobal('route', vi.fn(() => '/mock-route'));
    mockedUseForm.mockReturnValue(mockFormReturn());
  });

  it('renders the consent explanation text', () => {
    render(<BundledAiConsentModal {...defaultProps} />);
    expect(screen.getByText('AI Content Processing')).toBeInTheDocument();
    expect(screen.getByText(/sent to openai for processing/i)).toBeInTheDocument();
  });

  it('shows content processed bullet points', () => {
    render(<BundledAiConsentModal {...defaultProps} />);
    expect(screen.getByText(/page text from your wordpress site/i)).toBeInTheDocument();
    expect(screen.getByText(/ai prompt with rewrite instructions/i)).toBeInTheDocument();
  });

  it('shows revoke consent information', () => {
    render(<BundledAiConsentModal {...defaultProps} />);
    expect(screen.getByText(/revoke this consent anytime/i)).toBeInTheDocument();
  });

  it('"I agree" button posts to ai-consent.store route', async () => {
    const user = userEvent.setup();
    render(<BundledAiConsentModal {...defaultProps} />);
    await user.click(screen.getByRole('button', { name: /i agree/i }));
    expect(mockPost).toHaveBeenCalledWith('/mock-route', expect.objectContaining({
      onSuccess: expect.any(Function),
    }));
  });

  it('"Not now" button closes modal without posting', async () => {
    const onClose = vi.fn();
    const user = userEvent.setup();
    render(<BundledAiConsentModal {...defaultProps} onClose={onClose} />);
    await user.click(screen.getByRole('button', { name: /not now/i }));
    expect(onClose).toHaveBeenCalledOnce();
    expect(mockPost).not.toHaveBeenCalled();
  });

  it('shows error message when form has errors', () => {
    mockedUseForm.mockReturnValue(
      mockFormReturn({
        hasErrors: true,
        errors: { consent_type: 'Something went wrong.' },
      }),
    );
    render(<BundledAiConsentModal {...defaultProps} />);
    expect(screen.getByText('Something went wrong.')).toBeInTheDocument();
  });

  it('shows fallback error when no specific field error', () => {
    mockedUseForm.mockReturnValue(
      mockFormReturn({ hasErrors: true, errors: {} }),
    );
    render(<BundledAiConsentModal {...defaultProps} />);
    expect(screen.getByText(/something went wrong. try again/i)).toBeInTheDocument();
  });

  it('does not render when open is false', () => {
    render(<BundledAiConsentModal {...defaultProps} open={false} />);
    expect(screen.queryByText('AI Content Processing')).not.toBeInTheDocument();
  });
});
