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

import {ImagePickerProvider, useImagePickerContext} from './ImagePickerProvider'

// Mock useRequestPermissions hook
const mockRequestPermission = vi.fn()
vi.mock('../hooks/util/useRequestPermissions', () => ({
  useRequestPermissions: () => ({
    requestPermission: mockRequestPermission,
  }),
}))

// Mock useReportInteraction hook
const mockReportInteraction = vi.fn()
vi.mock('../internal/useReportInteraction', () => ({
  useReportInteraction: () => ({
    reportInteraction: mockReportInteraction,
  }),
}))

describe('ImagePickerProvider', () => {
  const originalMinisParams = window.minisParams

  beforeEach(() => {
    vi.clearAllMocks()
    // Default to granting permission
    mockRequestPermission.mockResolvedValue({granted: true})
    // Clear interaction reporting mock
    mockReportInteraction.mockClear()

    // Mock URL.createObjectURL and URL.revokeObjectURL for jsdom
    global.URL.createObjectURL = vi.fn(() => 'blob:mock-url')
    global.URL.revokeObjectURL = vi.fn()

    // Mock Image constructor for resizing
    global.Image = class MockImage {
      width = 1920
      height = 1080
      onload = null as any
      onerror = null as any
      src = ''

      constructor() {
        setTimeout(() => {
          if (this.onload) {
            this.onload()
          }
        }, 0)
      }
    } as any

    // Mock canvas methods
    HTMLCanvasElement.prototype.getContext = vi.fn(() => ({
      drawImage: vi.fn(),
    })) as any

    HTMLCanvasElement.prototype.toBlob = vi.fn(callback => {
      const blob = new Blob(['mock'], {type: 'image/jpeg'})
      callback(blob)
    }) as any
  })

  afterEach(() => {
    // Restore original minisParams
    window.minisParams = originalMinisParams
  })

  describe('Context', () => {
    it('throws error when used outside of provider', () => {
      // Silence console.error for this test
      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})

      expect(() => {
        renderHook(() => useImagePickerContext())
      }).toThrow(
        'useImagePickerContext must be used within an ImagePickerProvider'
      )

      consoleSpy.mockRestore()
    })

    it('provides context value when used within provider', () => {
      const {result} = renderHook(() => useImagePickerContext(), {
        wrapper: ({children}: {children: React.ReactNode}) => (
          <ImagePickerProvider>{children}</ImagePickerProvider>
        ),
      })

      expect(result.current).toHaveProperty('openCamera')
      expect(result.current).toHaveProperty('openGallery')
      expect(typeof result.current.openCamera).toBe('function')
      expect(typeof result.current.openGallery).toBe('function')
    })
  })

  describe('Hidden Inputs', () => {
    it('renders hidden file inputs', () => {
      const {container} = render(
        <ImagePickerProvider>
          <div>Test Content</div>
        </ImagePickerProvider>
      )

      const inputs = container.querySelectorAll('input[type="file"]')
      expect(inputs).toHaveLength(3)

      // Gallery input
      const galleryInput = inputs[0]
      expect(galleryInput).toHaveAttribute('accept', 'image/*')
      expect(galleryInput).not.toHaveAttribute('capture')
      expect(galleryInput).toHaveStyle({display: 'none'})

      // Front camera input
      const frontCameraInput = inputs[1]
      expect(frontCameraInput).toHaveAttribute('accept', 'image/*')
      expect(frontCameraInput).toHaveAttribute('capture', 'user')

      // Back camera input
      const backCameraInput = inputs[2]
      expect(backCameraInput).toHaveAttribute('accept', 'image/*')
      expect(backCameraInput).toHaveAttribute('capture', 'environment')
    })
  })

  describe('openGallery', () => {
    it('requests CAMERA permission before showing picker', async () => {
      mockRequestPermission.mockResolvedValue({granted: true})

      const TestComponent = () => {
        const {openGallery} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openGallery()
                .then(file => {
                  const span = document.createElement('span')
                  span.textContent = file.name
                  span.setAttribute('data-testid', 'selected-file')
                  document.body.appendChild(span)
                })
                .catch(() => {
                  // Ignore errors from cleanup
                })
            }
          >
            Open Gallery
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const galleryInput = container.querySelector(
        'input[type="file"]:not([capture])'
      ) as HTMLInputElement
      const clickSpy = vi.spyOn(galleryInput, 'click')

      // Click the button to open gallery
      const button = screen.getByText('Open Gallery')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Input should be clicked after permission request
      await vi.waitFor(() => {
        expect(clickSpy).toHaveBeenCalledTimes(1)
      })

      // Simulate file selection
      const file = new File(['test'], 'test.jpg', {type: 'image/jpeg'})
      Object.defineProperty(galleryInput, 'files', {
        value: [file],
        configurable: true,
      })

      fireEvent.change(galleryInput)

      // Check that the promise resolved with the file
      await vi.waitFor(() => {
        const selectedFile = document.querySelector(
          '[data-testid="selected-file"]'
        )
        expect(selectedFile?.textContent).toBe('test.jpg')
      })
    })

    it('handles cancel event', async () => {
      mockRequestPermission.mockResolvedValue({granted: true})

      const TestComponent = () => {
        const {openGallery} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openGallery().catch(error => {
                const span = document.createElement('span')
                span.textContent = error.message
                span.setAttribute('data-testid', 'cancel-message')
                document.body.appendChild(span)
              })
            }
          >
            Open Gallery
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const galleryInput = container.querySelector(
        'input[type="file"]:not([capture])'
      ) as HTMLInputElement

      const button = screen.getByText('Open Gallery')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Simulate cancel event
      await act(async () => {
        const cancelEvent = new Event('cancel', {bubbles: true})
        galleryInput.dispatchEvent(cancelEvent)
      })

      await vi.waitFor(() => {
        const cancelMessage = document.querySelector(
          '[data-testid="cancel-message"]'
        )
        expect(cancelMessage?.textContent).toBe('User cancelled file selection')
      })
    })

    it('still opens picker even if CAMERA permission is denied', async () => {
      mockRequestPermission.mockRejectedValue(new Error('Permission denied'))

      const TestComponent = () => {
        const {openGallery} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openGallery().catch(() => {
                // Ignore errors from cleanup
              })
            }
          >
            Open Gallery
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const galleryInput = container.querySelector(
        'input[type="file"]:not([capture])'
      ) as HTMLInputElement
      const clickSpy = vi.spyOn(galleryInput, 'click')

      const button = screen.getByText('Open Gallery')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Input should still be clicked even after permission rejection
      await vi.waitFor(() => {
        expect(clickSpy).toHaveBeenCalledTimes(1)
      })
    })
  })

  describe('openCamera', () => {
    it('requests CAMERA permission and opens camera if granted', async () => {
      mockRequestPermission.mockResolvedValue({granted: true})

      const TestComponent = () => {
        const {openCamera} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openCamera().catch(() => {
                // Ignore errors from cleanup
              })
            }
          >
            Open Camera
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const backCameraInput = container.querySelector(
        'input[capture="environment"]'
      ) as HTMLInputElement
      const clickSpy = vi.spyOn(backCameraInput, 'click')

      const button = screen.getByText('Open Camera')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Input should be clicked after permission is granted
      await vi.waitFor(() => {
        expect(clickSpy).toHaveBeenCalledTimes(1)
      })
    })

    it('triggers front camera input click when specified', async () => {
      mockRequestPermission.mockResolvedValue({granted: true})

      const TestComponent = () => {
        const {openCamera} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openCamera({cameraFacing: 'front'}).catch(() => {
                // Ignore errors from cleanup
              })
            }
          >
            Open Front Camera
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const frontCameraInput = container.querySelector(
        'input[capture="user"]'
      ) as HTMLInputElement
      const clickSpy = vi.spyOn(frontCameraInput, 'click')

      const button = screen.getByText('Open Front Camera')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Front camera input should be clicked after permission is granted
      await vi.waitFor(() => {
        expect(clickSpy).toHaveBeenCalledTimes(1)
      })
    })

    it('resolves with selected file from camera', async () => {
      mockRequestPermission.mockResolvedValue({granted: true})

      const TestComponent = () => {
        const {openCamera} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openCamera()
                .then(file => {
                  const span = document.createElement('span')
                  span.textContent = file.name
                  span.setAttribute('data-testid', 'camera-file')
                  document.body.appendChild(span)
                })
                .catch(() => {
                  // Ignore errors from cleanup
                })
            }
          >
            Open Camera
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const cameraInput = container.querySelector(
        'input[capture="environment"]'
      ) as HTMLInputElement

      const button = screen.getByText('Open Camera')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Simulate file capture
      const file = new File(['photo'], 'photo.jpg', {type: 'image/jpeg'})
      Object.defineProperty(cameraInput, 'files', {
        value: [file],
        configurable: true,
      })

      fireEvent.change(cameraInput)

      await vi.waitFor(() => {
        const cameraFile = document.querySelector('[data-testid="camera-file"]')
        expect(cameraFile?.textContent).toBe('photo.jpg')
      })
    })

    it('handles cancel event for camera', async () => {
      mockRequestPermission.mockResolvedValue({granted: true})

      const TestComponent = () => {
        const {openCamera} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openCamera().catch(error => {
                const span = document.createElement('span')
                span.textContent = error.message
                span.setAttribute('data-testid', 'camera-cancel')
                document.body.appendChild(span)
              })
            }
          >
            Open Camera
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const cameraInput = container.querySelector(
        'input[capture="environment"]'
      ) as HTMLInputElement

      const button = screen.getByText('Open Camera')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Simulate cancel event
      await act(async () => {
        const cancelEvent = new Event('cancel', {bubbles: true})
        cameraInput.dispatchEvent(cancelEvent)
      })

      await vi.waitFor(() => {
        const cancelMessage = document.querySelector(
          '[data-testid="camera-cancel"]'
        )
        expect(cancelMessage?.textContent).toBe('User cancelled camera')
      })
    })

    it('rejects with error if CAMERA permission is not granted', async () => {
      mockRequestPermission.mockResolvedValue({granted: false})

      const TestComponent = () => {
        const {openCamera} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openCamera().catch(error => {
                const span = document.createElement('span')
                span.textContent = error.message
                span.setAttribute('data-testid', 'permission-error')
                document.body.appendChild(span)
              })
            }
          >
            Open Camera
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const cameraInput = container.querySelector(
        'input[capture="environment"]'
      ) as HTMLInputElement
      const clickSpy = vi.spyOn(cameraInput, 'click')

      const button = screen.getByText('Open Camera')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Input should NOT be clicked when permission is denied
      expect(clickSpy).not.toHaveBeenCalled()

      // Should show error message
      await vi.waitFor(() => {
        const errorMessage = document.querySelector(
          '[data-testid="permission-error"]'
        )
        expect(errorMessage?.textContent).toBe('Camera permission not granted')
      })
    })

    it('rejects with error if permission request fails', async () => {
      mockRequestPermission.mockRejectedValue(
        new Error('Permission request failed')
      )

      const TestComponent = () => {
        const {openCamera} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openCamera().catch(error => {
                const span = document.createElement('span')
                span.textContent = error.message
                span.setAttribute('data-testid', 'permission-error')
                document.body.appendChild(span)
              })
            }
          >
            Open Camera
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const cameraInput = container.querySelector(
        'input[capture="environment"]'
      ) as HTMLInputElement
      const clickSpy = vi.spyOn(cameraInput, 'click')

      const button = screen.getByText('Open Camera')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Input should NOT be clicked when permission request fails
      expect(clickSpy).not.toHaveBeenCalled()

      // Should show error message
      await vi.waitFor(() => {
        const errorMessage = document.querySelector(
          '[data-testid="permission-error"]'
        )
        expect(errorMessage?.textContent).toBe('Camera permission not granted')
      })
    })
  })

  describe('Multiple Picker Handling', () => {
    it('rejects previous promise when new picker is opened', async () => {
      mockRequestPermission.mockResolvedValue({granted: true})

      const TestComponent = () => {
        const {openCamera, openGallery} = useImagePickerContext()

        return (
          <>
            <button
              type="button"
              onClick={() =>
                openGallery().catch(error => {
                  const span = document.createElement('span')
                  span.textContent = error.message
                  span.setAttribute('data-testid', 'gallery-error')
                  document.body.appendChild(span)
                })
              }
            >
              Open Gallery
            </button>
            <button
              type="button"
              onClick={() =>
                openCamera().catch(() => {
                  // Ignore errors from cleanup
                })
              }
            >
              Open Camera
            </button>
          </>
        )
      }

      render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      // Open gallery first
      const galleryButton = screen.getByText('Open Gallery')
      fireEvent.click(galleryButton)

      // Then immediately open camera
      const cameraButton = screen.getByText('Open Camera')
      fireEvent.click(cameraButton)

      await vi.waitFor(() => {
        const errorMessage = document.querySelector(
          '[data-testid="gallery-error"]'
        )
        expect(errorMessage?.textContent).toBe(
          'New file picker opened before previous completed'
        )
      })
    })
  })

  describe('Cleanup', () => {
    it('clears input value after file selection', async () => {
      mockRequestPermission.mockResolvedValue({granted: true})

      const TestComponent = () => {
        const {openGallery} = useImagePickerContext()

        return (
          <button
            type="button"
            onClick={() =>
              openGallery().catch(() => {
                // Ignore errors from cleanup
              })
            }
          >
            Open Gallery
          </button>
        )
      }

      const {container} = render(
        <ImagePickerProvider>
          <TestComponent />
        </ImagePickerProvider>
      )

      const galleryInput = container.querySelector(
        'input[type="file"]:not([capture])'
      ) as HTMLInputElement

      const button = screen.getByText('Open Gallery')
      fireEvent.click(button)

      // Wait for permission request to complete
      await vi.waitFor(() => {
        expect(mockRequestPermission).toHaveBeenCalledWith({
          permission: 'CAMERA',
        })
      })

      // Set file and trigger change
      const file = new File(['test'], 'test.jpg', {type: 'image/jpeg'})
      Object.defineProperty(galleryInput, 'files', {
        value: [file],
        configurable: true,
      })

      fireEvent.change(galleryInput)

      // Check that input value was cleared
      expect(galleryInput.value).toBe('')
    })
  })

  describe('Interaction Reporting', () => {
    describe('Gallery interactions', () => {
      it('reports image_picker_open when gallery is opened', async () => {
        mockRequestPermission.mockResolvedValue({granted: true})

        const TestComponent = () => {
          const {openGallery} = useImagePickerContext()

          return (
            <button
              type="button"
              onClick={() =>
                openGallery().catch(() => {
                  // Ignore errors from cleanup
                })
              }
            >
              Open Gallery
            </button>
          )
        }

        render(
          <ImagePickerProvider>
            <TestComponent />
          </ImagePickerProvider>
        )

        const button = screen.getByText('Open Gallery')
        fireEvent.click(button)

        // Wait for interaction to be reported
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'image_picker_open',
          })
        })
      })

      it('reports image_picker_success when file is selected', async () => {
        mockRequestPermission.mockResolvedValue({granted: true})

        const TestComponent = () => {
          const {openGallery} = useImagePickerContext()

          return (
            <button
              type="button"
              onClick={() =>
                openGallery().catch(() => {
                  // Ignore errors from cleanup
                })
              }
            >
              Open Gallery
            </button>
          )
        }

        const {container} = render(
          <ImagePickerProvider>
            <TestComponent />
          </ImagePickerProvider>
        )

        const galleryInput = container.querySelector(
          'input[type="file"]:not([capture])'
        ) as HTMLInputElement

        const button = screen.getByText('Open Gallery')
        fireEvent.click(button)

        // Wait for permission and initial interaction
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'image_picker_open',
          })
        })

        // Clear mock to check only for success interaction
        mockReportInteraction.mockClear()

        // Simulate file selection
        const file = new File(['test'], 'test.jpg', {type: 'image/jpeg'})
        Object.defineProperty(galleryInput, 'files', {
          value: [file],
          configurable: true,
        })

        await act(async () => {
          fireEvent.change(galleryInput)
        })

        // Check success was reported
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'image_picker_success',
          })
        })
      })

      it('reports image_picker_error when interrupted by new picker', async () => {
        mockRequestPermission.mockResolvedValue({granted: true})

        const TestComponent = () => {
          const {openGallery, openCamera} = useImagePickerContext()

          return (
            <>
              <button
                type="button"
                onClick={() =>
                  openGallery().catch(() => {
                    // Expected to fail
                  })
                }
              >
                Open Gallery
              </button>
              <button
                type="button"
                onClick={() =>
                  openCamera().catch(() => {
                    // Ignore errors
                  })
                }
              >
                Open Camera
              </button>
            </>
          )
        }

        render(
          <ImagePickerProvider>
            <TestComponent />
          </ImagePickerProvider>
        )

        // Open gallery first
        const galleryButton = screen.getByText('Open Gallery')
        fireEvent.click(galleryButton)

        // Wait for gallery open to be reported
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'image_picker_open',
          })
        })

        mockReportInteraction.mockClear()

        // Open camera to interrupt gallery
        const cameraButton = screen.getByText('Open Camera')
        fireEvent.click(cameraButton)

        // Check error was reported for interrupted gallery operation
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'image_picker_error',
            interactionValue:
              'New file picker opened before previous completed',
          })
        })
      })
    })

    describe('Camera interactions', () => {
      it('reports camera_open when camera is opened', async () => {
        mockRequestPermission.mockResolvedValue({granted: true})

        const TestComponent = () => {
          const {openCamera} = useImagePickerContext()

          return (
            <button
              type="button"
              onClick={() =>
                openCamera().catch(() => {
                  // Ignore errors from cleanup
                })
              }
            >
              Open Camera
            </button>
          )
        }

        render(
          <ImagePickerProvider>
            <TestComponent />
          </ImagePickerProvider>
        )

        const button = screen.getByText('Open Camera')
        fireEvent.click(button)

        // Wait for interaction to be reported
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'camera_open',
          })
        })
      })

      it('reports camera_success when photo is captured', async () => {
        mockRequestPermission.mockResolvedValue({granted: true})

        const TestComponent = () => {
          const {openCamera} = useImagePickerContext()

          return (
            <button
              type="button"
              onClick={() =>
                openCamera().catch(() => {
                  // Ignore errors from cleanup
                })
              }
            >
              Open Camera
            </button>
          )
        }

        const {container} = render(
          <ImagePickerProvider>
            <TestComponent />
          </ImagePickerProvider>
        )

        const cameraInput = container.querySelector(
          'input[capture="environment"]'
        ) as HTMLInputElement

        const button = screen.getByText('Open Camera')
        fireEvent.click(button)

        // Wait for camera open to be reported
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'camera_open',
          })
        })

        mockReportInteraction.mockClear()

        // Simulate photo capture
        const file = new File(['photo'], 'photo.jpg', {type: 'image/jpeg'})
        Object.defineProperty(cameraInput, 'files', {
          value: [file],
          configurable: true,
        })

        await act(async () => {
          fireEvent.change(cameraInput)
        })

        // Check success was reported
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'camera_success',
          })
        })
      })

      it('reports camera_error when interrupted by new picker', async () => {
        mockRequestPermission.mockResolvedValue({granted: true})

        const TestComponent = () => {
          const {openCamera, openGallery} = useImagePickerContext()

          return (
            <>
              <button
                type="button"
                onClick={() =>
                  openCamera().catch(() => {
                    // Expected to fail
                  })
                }
              >
                Open Camera
              </button>
              <button
                type="button"
                onClick={() =>
                  openGallery().catch(() => {
                    // Ignore errors
                  })
                }
              >
                Open Gallery
              </button>
            </>
          )
        }

        render(
          <ImagePickerProvider>
            <TestComponent />
          </ImagePickerProvider>
        )

        // Open camera first
        const cameraButton = screen.getByText('Open Camera')
        fireEvent.click(cameraButton)

        // Wait for camera open to be reported
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'camera_open',
          })
        })

        mockReportInteraction.mockClear()

        // Open gallery to interrupt camera
        const galleryButton = screen.getByText('Open Gallery')
        fireEvent.click(galleryButton)

        // Check error was reported for interrupted camera operation
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'camera_error',
            interactionValue:
              'New file picker opened before previous completed',
          })
        })
      })

      it('reports camera_error when permission is denied', async () => {
        mockRequestPermission.mockResolvedValue({granted: false})

        const TestComponent = () => {
          const {openCamera} = useImagePickerContext()

          return (
            <button
              type="button"
              onClick={() =>
                openCamera().catch(() => {
                  // Expected to fail
                })
              }
            >
              Open Camera
            </button>
          )
        }

        render(
          <ImagePickerProvider>
            <TestComponent />
          </ImagePickerProvider>
        )

        const button = screen.getByText('Open Camera')
        fireEvent.click(button)

        // Wait for permission request
        await vi.waitFor(() => {
          expect(mockRequestPermission).toHaveBeenCalled()
        })

        // Camera open should be reported
        expect(mockReportInteraction).toHaveBeenCalledWith({
          interactionType: 'camera_open',
        })

        // Error interaction should be reported for permission denial
        await vi.waitFor(() => {
          expect(mockReportInteraction).toHaveBeenCalledWith({
            interactionType: 'camera_error',
            interactionValue: 'Camera permission not granted',
          })
        })
      })
    })
  })
})
