/**
 * Add Sensor Screen - BLE Cleanup Tests
 * Tests that BLE scanning stops when user navigates away from the screen
 */

import React from 'react';
import { render, waitFor } from '@testing-library/react-native';
import { useLocalSearchParams, useFocusEffect } from 'expo-router';
import AddSensorScreen from '../[id]/add-sensor';
import { useBLE } from '@/contexts/BLEContext';
import { useBeneficiary } from '@/contexts/BeneficiaryContext';

// Mock dependencies
jest.mock('expo-router', () => ({
  useLocalSearchParams: jest.fn(),
  router: {
    push: jest.fn(),
    back: jest.fn(),
  },
  useFocusEffect: jest.fn(),
}));

jest.mock('@/contexts/BLEContext', () => ({
  useBLE: jest.fn(),
}));

jest.mock('@/contexts/BeneficiaryContext', () => ({
  useBeneficiary: jest.fn(),
}));

jest.mock('expo-device', () => ({
  isDevice: true,
}));

describe('AddSensorScreen - BLE cleanup', () => {
  const mockStopScan = jest.fn();
  const mockScanDevices = jest.fn();

  beforeEach(() => {
    jest.clearAllMocks();

    // Mock route params
    (useLocalSearchParams as jest.Mock).mockReturnValue({ id: '1' });

    // Mock beneficiary context
    (useBeneficiary as jest.Mock).mockReturnValue({
      currentBeneficiary: {
        id: 1,
        name: 'Maria',
      },
    });

    // Mock BLE context
    (useBLE as jest.Mock).mockReturnValue({
      foundDevices: [],
      isScanning: false,
      connectedDevices: new Set(),
      isBLEAvailable: true,
      error: null,
      scanDevices: mockScanDevices,
      stopScan: mockStopScan,
      connectDevice: jest.fn(),
      disconnectDevice: jest.fn(),
      getWiFiList: jest.fn(),
      setWiFi: jest.fn(),
      getCurrentWiFi: jest.fn(),
      rebootDevice: jest.fn(),
      cleanupBLE: jest.fn(),
      clearError: jest.fn(),
    });
  });

  it('should register cleanup handler with useFocusEffect', () => {
    render(<AddSensorScreen />);

    expect(useFocusEffect).toHaveBeenCalled();
  });

  it('should stop scan when cleanup handler is called while scanning', () => {
    // Mock scanning state
    (useBLE as jest.Mock).mockReturnValue({
      foundDevices: [],
      isScanning: true, // Scan in progress
      connectedDevices: new Set(),
      isBLEAvailable: true,
      error: null,
      scanDevices: mockScanDevices,
      stopScan: mockStopScan,
      connectDevice: jest.fn(),
      disconnectDevice: jest.fn(),
      getWiFiList: jest.fn(),
      setWiFi: jest.fn(),
      getCurrentWiFi: jest.fn(),
      rebootDevice: jest.fn(),
      cleanupBLE: jest.fn(),
      clearError: jest.fn(),
    });

    render(<AddSensorScreen />);

    // Get the cleanup function from useFocusEffect
    const focusEffectCall = (useFocusEffect as jest.Mock).mock.calls[0][0];
    const cleanupFn = focusEffectCall(); // Call the effect to get cleanup function

    // Simulate screen blur by calling cleanup
    if (cleanupFn) {
      cleanupFn();
    }

    expect(mockStopScan).toHaveBeenCalled();
  });

  it('should not stop scan when cleanup handler is called and not scanning', () => {
    // Mock idle state
    (useBLE as jest.Mock).mockReturnValue({
      foundDevices: [],
      isScanning: false, // Not scanning
      connectedDevices: new Set(),
      isBLEAvailable: true,
      error: null,
      scanDevices: mockScanDevices,
      stopScan: mockStopScan,
      connectDevice: jest.fn(),
      disconnectDevice: jest.fn(),
      getWiFiList: jest.fn(),
      setWiFi: jest.fn(),
      getCurrentWiFi: jest.fn(),
      rebootDevice: jest.fn(),
      cleanupBLE: jest.fn(),
      clearError: jest.fn(),
    });

    render(<AddSensorScreen />);

    // Get the cleanup function from useFocusEffect
    const focusEffectCall = (useFocusEffect as jest.Mock).mock.calls[0][0];
    const cleanupFn = focusEffectCall();

    // Simulate screen blur by calling cleanup
    if (cleanupFn) {
      cleanupFn();
    }

    // stopScan should not be called when not scanning
    expect(mockStopScan).not.toHaveBeenCalled();
  });

  it('should cleanup when component unmounts during active scan', () => {
    (useBLE as jest.Mock).mockReturnValue({
      foundDevices: [
        { id: 'device-1', name: 'WP_497_81a14c', mac: '81A14C', rssi: -55, wellId: 497 },
      ],
      isScanning: true,
      connectedDevices: new Set(),
      isBLEAvailable: true,
      error: null,
      scanDevices: mockScanDevices,
      stopScan: mockStopScan,
      connectDevice: jest.fn(),
      disconnectDevice: jest.fn(),
      getWiFiList: jest.fn(),
      setWiFi: jest.fn(),
      getCurrentWiFi: jest.fn(),
      rebootDevice: jest.fn(),
      cleanupBLE: jest.fn(),
      clearError: jest.fn(),
    });

    const { unmount } = render(<AddSensorScreen />);

    // Get the cleanup function
    const focusEffectCall = (useFocusEffect as jest.Mock).mock.calls[0][0];
    const cleanupFn = focusEffectCall();

    // Unmount component
    unmount();

    // Cleanup should have been called during unmount
    if (cleanupFn) {
      cleanupFn();
    }

    expect(mockStopScan).toHaveBeenCalled();
  });
});
