/**
 * Tests for AugmentationConfig component.
 *
 * TDD Phase 1: RED - Write tests first, then implement to pass.
 */

import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { AugmentationConfig } from './AugmentationConfig'
import { augmentationApi } from '../api/endpoints/augmentation'
import type { ReactNode } from 'react'

// Mock the API
vi.mock('../api/endpoints/augmentation', () => ({
  augmentationApi: {
    getTypes: vi.fn(),
    getPresets: vi.fn(),
    preview: vi.fn(),
    previewConfig: vi.fn(),
    createBatch: vi.fn(),
  },
}))

// Default mock data
const mockTypes = {
  augmentation_types: [
    {
      name: 'gaussian_noise',
      description: 'Adds Gaussian noise to simulate sensor noise',
      affects_geometry: false,
      stage: 'noise',
      default_params: { mean: 0, std: 15 },
    },
    {
      name: 'perspective_warp',
      description: 'Applies perspective transformation',
      affects_geometry: true,
      stage: 'geometric',
      default_params: { max_warp: 0.02 },
    },
    {
      name: 'gaussian_blur',
      description: 'Applies Gaussian blur',
      affects_geometry: false,
      stage: 'blur',
      default_params: { kernel_size: 5 },
    },
  ],
}

const mockPresets = {
  presets: [
    { name: 'conservative', description: 'Safe augmentations for high-quality documents' },
    { name: 'moderate', description: 'Balanced augmentation settings' },
    { name: 'aggressive', description: 'Strong augmentations for data diversity' },
  ],
}

// Test wrapper with QueryClient
const createWrapper = () => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
    },
  })
  return ({ children }: { children: ReactNode }) => (
    <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  )
}

describe('AugmentationConfig', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    vi.mocked(augmentationApi.getTypes).mockResolvedValue(mockTypes)
    vi.mocked(augmentationApi.getPresets).mockResolvedValue(mockPresets)
  })

  describe('rendering', () => {
    it('should render enable checkbox', async () => {
      render(
        <AugmentationConfig
          enabled={false}
          onEnabledChange={vi.fn()}
          config={{}}
          onConfigChange={vi.fn()}
        />,
        { wrapper: createWrapper() }
      )

      expect(screen.getByRole('checkbox', { name: /enable augmentation/i })).toBeInTheDocument()
    })

    it('should be collapsed when disabled', () => {
      render(
        <AugmentationConfig
          enabled={false}
          onEnabledChange={vi.fn()}
          config={{}}
          onConfigChange={vi.fn()}
        />,
        { wrapper: createWrapper() }
      )

      // Config options should not be visible
      expect(screen.queryByText(/preset/i)).not.toBeInTheDocument()
    })

    it('should expand when enabled', async () => {
      render(
        <AugmentationConfig
          enabled={true}
          onEnabledChange={vi.fn()}
          config={{}}
          onConfigChange={vi.fn()}
        />,
        { wrapper: createWrapper() }
      )

      await waitFor(() => {
        expect(screen.getByText(/preset/i)).toBeInTheDocument()
      })
    })
  })

  describe('preset selection', () => {
    it('should display available presets', async () => {
      render(
        <AugmentationConfig
          enabled={true}
          onEnabledChange={vi.fn()}
          config={{}}
          onConfigChange={vi.fn()}
        />,
        { wrapper: createWrapper() }
      )

      await waitFor(() => {
        expect(screen.getByText('conservative')).toBeInTheDocument()
        expect(screen.getByText('moderate')).toBeInTheDocument()
        expect(screen.getByText('aggressive')).toBeInTheDocument()
      })
    })

    it('should call onConfigChange when preset is selected', async () => {
      const user = userEvent.setup()
      const onConfigChange = vi.fn()

      render(
        <AugmentationConfig
          enabled={true}
          onEnabledChange={vi.fn()}
          config={{}}
          onConfigChange={onConfigChange}
        />,
        { wrapper: createWrapper() }
      )

      await waitFor(() => {
        expect(screen.getByText('moderate')).toBeInTheDocument()
      })

      await user.click(screen.getByText('moderate'))

      expect(onConfigChange).toHaveBeenCalled()
    })
  })

  describe('enable toggle', () => {
    it('should call onEnabledChange when checkbox is toggled', async () => {
      const user = userEvent.setup()
      const onEnabledChange = vi.fn()

      render(
        <AugmentationConfig
          enabled={false}
          onEnabledChange={onEnabledChange}
          config={{}}
          onConfigChange={vi.fn()}
        />,
        { wrapper: createWrapper() }
      )

      await user.click(screen.getByRole('checkbox', { name: /enable augmentation/i }))

      expect(onEnabledChange).toHaveBeenCalledWith(true)
    })
  })

  describe('augmentation types', () => {
    it('should display augmentation types when in custom mode', async () => {
      render(
        <AugmentationConfig
          enabled={true}
          onEnabledChange={vi.fn()}
          config={{}}
          onConfigChange={vi.fn()}
          showCustomOptions={true}
        />,
        { wrapper: createWrapper() }
      )

      await waitFor(() => {
        expect(screen.getByText(/gaussian_noise/i)).toBeInTheDocument()
        expect(screen.getByText(/perspective_warp/i)).toBeInTheDocument()
      })
    })

    it('should indicate which augmentations affect geometry', async () => {
      render(
        <AugmentationConfig
          enabled={true}
          onEnabledChange={vi.fn()}
          config={{}}
          onConfigChange={vi.fn()}
          showCustomOptions={true}
        />,
        { wrapper: createWrapper() }
      )

      await waitFor(() => {
        // perspective_warp affects geometry
        const perspectiveItem = screen.getByText(/perspective_warp/i).closest('div')
        expect(perspectiveItem).toHaveTextContent(/affects bbox/i)
      })
    })
  })

  describe('loading state', () => {
    it('should show loading indicator while fetching types', () => {
      vi.mocked(augmentationApi.getTypes).mockImplementation(
        () => new Promise(() => {})
      )

      render(
        <AugmentationConfig
          enabled={true}
          onEnabledChange={vi.fn()}
          config={{}}
          onConfigChange={vi.fn()}
        />,
        { wrapper: createWrapper() }
      )

      expect(screen.getByTestId('augmentation-loading')).toBeInTheDocument()
    })
  })
})
