// BLE Context - Global state for Bluetooth management

import React, { createContext, useContext, useState, useCallback, ReactNode } from 'react';
import { bleManager, WPDevice, WiFiNetwork, WiFiStatus, isBLEAvailable } from '@/services/ble';

interface BLEContextType {
  // State
  foundDevices: WPDevice[];
  isScanning: boolean;
  connectedDevices: Set<string>;
  isBLEAvailable: boolean;
  error: string | null;

  // Actions
  scanDevices: () => Promise<void>;
  stopScan: () => void;
  connectDevice: (deviceId: string) => Promise<boolean>;
  disconnectDevice: (deviceId: string) => Promise<void>;
  getWiFiList: (deviceId: string) => Promise<WiFiNetwork[]>;
  setWiFi: (deviceId: string, ssid: string, password: string) => Promise<boolean>;
  getCurrentWiFi: (deviceId: string) => Promise<WiFiStatus | null>;
  rebootDevice: (deviceId: string) => Promise<void>;
  clearError: () => void;
}

const BLEContext = createContext<BLEContextType | undefined>(undefined);

export function BLEProvider({ children }: { children: ReactNode }) {
  const [foundDevices, setFoundDevices] = useState<WPDevice[]>([]);
  const [isScanning, setIsScanning] = useState(false);
  const [connectedDevices, setConnectedDevices] = useState<Set<string>>(new Set());
  const [error, setError] = useState<string | null>(null);

  const scanDevices = useCallback(async () => {
    try {
      setError(null);
      setIsScanning(true);
      const devices = await bleManager.scanDevices();
      // Sort by RSSI (strongest first)
      const sorted = devices.sort((a, b) => b.rssi - a.rssi);
      setFoundDevices(sorted);
    } catch (err: any) {
      console.error('[BLEContext] Scan error:', err);
      setError(err.message || 'Failed to scan for devices');
      throw err;
    } finally {
      setIsScanning(false);
    }
  }, []);

  const stopScan = useCallback(() => {
    bleManager.stopScan();
    setIsScanning(false);
  }, []);

  const connectDevice = useCallback(async (deviceId: string): Promise<boolean> => {
    try {
      setError(null);
      const success = await bleManager.connectDevice(deviceId);
      if (success) {
        setConnectedDevices(prev => new Set(prev).add(deviceId));
      }
      return success;
    } catch (err: any) {
      console.error('[BLEContext] Connect error:', err);
      setError(err.message || 'Failed to connect to device');
      return false;
    }
  }, []);

  const disconnectDevice = useCallback(async (deviceId: string): Promise<void> => {
    try {
      await bleManager.disconnectDevice(deviceId);
      setConnectedDevices(prev => {
        const next = new Set(prev);
        next.delete(deviceId);
        return next;
      });
    } catch (err: any) {
      console.error('[BLEContext] Disconnect error:', err);
      setError(err.message || 'Failed to disconnect device');
    }
  }, []);

  const getWiFiList = useCallback(async (deviceId: string): Promise<WiFiNetwork[]> => {
    try {
      setError(null);
      return await bleManager.getWiFiList(deviceId);
    } catch (err: any) {
      console.error('[BLEContext] Get WiFi list error:', err);
      setError(err.message || 'Failed to get WiFi networks');
      throw err;
    }
  }, []);

  const setWiFi = useCallback(
    async (deviceId: string, ssid: string, password: string): Promise<boolean> => {
      try {
        setError(null);
        return await bleManager.setWiFi(deviceId, ssid, password);
      } catch (err: any) {
        console.error('[BLEContext] Set WiFi error:', err);
        setError(err.message || 'Failed to configure WiFi');
        throw err;
      }
    },
    []
  );

  const getCurrentWiFi = useCallback(
    async (deviceId: string): Promise<WiFiStatus | null> => {
      try {
        setError(null);
        return await bleManager.getCurrentWiFi(deviceId);
      } catch (err: any) {
        console.error('[BLEContext] Get current WiFi error:', err);
        setError(err.message || 'Failed to get current WiFi');
        throw err;
      }
    },
    []
  );

  const rebootDevice = useCallback(async (deviceId: string): Promise<void> => {
    try {
      setError(null);
      await bleManager.rebootDevice(deviceId);
      // Remove from connected devices
      setConnectedDevices(prev => {
        const next = new Set(prev);
        next.delete(deviceId);
        return next;
      });
    } catch (err: any) {
      console.error('[BLEContext] Reboot error:', err);
      setError(err.message || 'Failed to reboot device');
      throw err;
    }
  }, []);

  const clearError = useCallback(() => {
    setError(null);
  }, []);

  const value: BLEContextType = {
    foundDevices,
    isScanning,
    connectedDevices,
    isBLEAvailable,
    error,
    scanDevices,
    stopScan,
    connectDevice,
    disconnectDevice,
    getWiFiList,
    setWiFi,
    getCurrentWiFi,
    rebootDevice,
    clearError,
  };

  return <BLEContext.Provider value={value}>{children}</BLEContext.Provider>;
}

export function useBLE() {
  const context = useContext(BLEContext);
  if (context === undefined) {
    throw new Error('useBLE must be used within a BLEProvider');
  }
  return context;
}
