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

const mockPut = vi.fn();

vi.mock('@inertiajs/react', async () => {
  const actual = await vi.importActual('@inertiajs/react');
  return {
    ...actual,
    Head: ({ title }: { title: string }) => <title>{title}</title>,
    router: { delete: vi.fn() },
    useForm: () => ({
      data: {
        model: 'gpt-4o-mini',
        temperature: 0.7,
        top_p: 1,
        max_output_tokens: 4096,
        custom_instructions_enabled: false,
        custom_instructions: '',
      },
      setData: vi.fn(),
      put: mockPut,
      processing: false,
      errors: {},
      isDirty: false,
    }),
  };
});

vi.mock('@/hooks/useUnsavedChanges', () => ({
  useUnsavedChanges: vi.fn(),
}));

vi.mock('@/Components/Navigation/SiteNav', () => ({
  default: () => <div data-testid="site-nav" />,
}));

vi.mock('@/Components/ui/confirm-dialog', () => ({
  ConfirmDialog: ({ open, title }: { open: boolean; title: string }) =>
    open ? <div data-testid="confirm-dialog">{title}</div> : null,
}));

vi.mock('@/Layouts/DashboardLayout', () => ({
  default: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="dashboard-layout">{children}</div>
  ),
}));

vi.mock('@/Components/ui/select', () => ({
  Select: ({ children, value }: { children: React.ReactNode; value: string }) => (
    <div data-testid="select" data-value={value}>
      {children}
    </div>
  ),
  SelectTrigger: ({ children, id }: { children: React.ReactNode; id?: string }) => (
    <button data-testid="select-trigger" id={id}>
      {children}
    </button>
  ),
  SelectValue: () => <span data-testid="select-value">gpt-4o-mini</span>,
  SelectContent: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="select-content">{children}</div>
  ),
  SelectItem: ({ children, value }: { children: React.ReactNode; value: string }) => (
    <div data-testid="select-item" data-value={value}>
      {children}
    </div>
  ),
}));

vi.mock('@/Components/ui/slider', () => ({
  Slider: ({
    id,
    min,
    max,
    step,
    value,
  }: {
    id?: string;
    min: number;
    max: number;
    step: number;
    value: number[];
  }) => (
    <div
      data-testid={`slider-${id ?? 'unknown'}`}
      data-min={min}
      data-max={max}
      data-step={step}
      data-value={value[0]}
      role="slider"
      aria-valuenow={value[0]}
      aria-valuemin={min}
      aria-valuemax={max}
    />
  ),
}));

vi.mock('@/Components/ui/tooltip', () => ({
  TooltipProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
  Tooltip: ({ children }: { children: React.ReactNode }) => <>{children}</>,
  TooltipTrigger: ({ children }: { children: React.ReactNode }) => <>{children}</>,
  TooltipContent: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="tooltip-content">{children}</div>
  ),
}));

import SiteAiSettings from './Ai';

const defaultProps = {
  site: { id: 1, name: 'Test Site', domain: 'https://test.com' },
  settings: null,
  defaults: {
    temperature_default: 0.7,
    temperature_min: 0,
    temperature_max: 2,
    top_p_default: 1,
    top_p_min: 0,
    top_p_max: 1,
    max_output_tokens_default: 4096,
    max_output_tokens_min: 256,
    max_output_tokens_max: 16384,
  },
  allowedModels: ['gpt-4o-mini', 'gpt-4o', 'gpt-4-turbo'],
};

describe('Sites/Settings/Ai', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.stubGlobal(
      'route',
      vi.fn(() => '/mock-route'),
    );
  });

  it('renders page title with site name', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(document.querySelector('title')).toHaveTextContent('Test Site - AI Settings');
  });

  it('renders heading "AI Settings"', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(screen.getByRole('heading', { name: /ai settings/i })).toBeInTheDocument();
  });

  it('renders model select with allowed models', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(screen.getByText('Model')).toBeInTheDocument();

    const items = screen.getAllByTestId('select-item');
    expect(items).toHaveLength(3);
    expect(items[0]).toHaveTextContent('gpt-4o-mini');
    expect(items[1]).toHaveTextContent('gpt-4o');
    expect(items[2]).toHaveTextContent('gpt-4-turbo');
  });

  it('renders temperature slider with correct range', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(screen.getByText(/temperature/i)).toBeInTheDocument();

    const slider = screen.getByTestId('slider-ai-temperature');
    expect(slider).toHaveAttribute('data-min', '0');
    expect(slider).toHaveAttribute('data-max', '2');
    expect(slider).toHaveAttribute('data-value', '0.7');
  });

  it('renders top_p slider with correct range', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(screen.getByText(/top p/i)).toBeInTheDocument();

    const slider = screen.getByTestId('slider-ai-top-p');
    expect(slider).toHaveAttribute('data-min', '0');
    expect(slider).toHaveAttribute('data-max', '1');
    expect(slider).toHaveAttribute('data-value', '1');
  });

  it('renders max output tokens input', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(screen.getByText(/max output tokens/i)).toBeInTheDocument();

    const input = screen.getByDisplayValue('4096');
    expect(input).toHaveAttribute('type', 'number');
    expect(input).toHaveAttribute('min', '256');
    expect(input).toHaveAttribute('max', '16384');
  });

  it('renders custom instructions checkbox unchecked by default', () => {
    render(<SiteAiSettings {...defaultProps} />);

    const checkbox = screen.getByRole('checkbox');
    expect(checkbox).not.toBeChecked();
    expect(screen.getByText(/enable custom instructions/i)).toBeInTheDocument();
  });

  it('renders Save Settings button', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(screen.getByRole('button', { name: /save settings/i })).toBeInTheDocument();
  });

  it('renders Reset to Defaults button', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(screen.getByRole('button', { name: /reset to defaults/i })).toBeInTheDocument();
  });

  it('shows SiteNav component', () => {
    render(<SiteAiSettings {...defaultProps} />);

    expect(screen.getByTestId('site-nav')).toBeInTheDocument();
  });

  it('associates labels with form controls via htmlFor', () => {
    render(<SiteAiSettings {...defaultProps} />);

    const modelLabel = screen.getByText('Model');
    expect(modelLabel).toHaveAttribute('for', 'ai-model');

    const maxTokensLabel = screen.getByText('Max output tokens');
    expect(maxTokensLabel).toHaveAttribute('for', 'ai-max-tokens');
  });

  it('renders help icons next to labels', () => {
    const { container } = render(<SiteAiSettings {...defaultProps} />);

    // Each LabelWithTooltip renders a HelpCircle SVG (lucide icon)
    const helpIcons = container.querySelectorAll('.cursor-help');
    expect(helpIcons.length).toBeGreaterThanOrEqual(4);
  });

  it('renders tooltip content for all settings', () => {
    render(<SiteAiSettings {...defaultProps} />);

    const tooltips = screen.getAllByTestId('tooltip-content');
    expect(tooltips.length).toBeGreaterThanOrEqual(4);

    expect(screen.getByText(/controls randomness/i)).toBeInTheDocument();
    expect(screen.getByText(/controls diversity via nucleus/i)).toBeInTheDocument();
    expect(screen.getByText(/maximum length of the generated content/i)).toBeInTheDocument();
    expect(screen.getByText(/the ai model used for content generation/i)).toBeInTheDocument();
  });
});
