import React, { useState, useCallback, useEffect } from 'react';
import {
  View,
  Text,
  StyleSheet,
  TouchableOpacity,
  ActivityIndicator,
  FlatList,
  Linking,
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { useBLE } from '@/contexts/BLEContext';
import { WPDevice } from '@/services/ble/types';
import {
  WiFiSignalIndicator,
  getSignalStrengthLabel,
  getSignalStrengthColor,
} from '@/components/WiFiSignalIndicator';
import {
  AppColors,
  BorderRadius,
  FontSizes,
  FontWeights,
  Spacing,
  Shadows,
} from '@/constants/theme';

export type SelectionMode = 'single' | 'multiple' | 'none';

export interface BLEScannerProps {
  /** Callback when device(s) are selected */
  onDevicesSelected?: (devices: WPDevice[]) => void;
  /** Callback when a single device is selected (convenience for single mode) */
  onDeviceSelected?: (device: WPDevice) => void;
  /** Selection mode: 'single', 'multiple', or 'none' */
  selectionMode?: SelectionMode;
  /** Whether to auto-start scanning when component mounts */
  autoScan?: boolean;
  /** Custom filter function for devices */
  deviceFilter?: (device: WPDevice) => boolean;
  /** Device IDs that are already connected/added (will show as disabled) */
  disabledDeviceIds?: Set<string>;
  /** Show instructions header */
  showInstructions?: boolean;
  /** Custom empty state message */
  emptyStateMessage?: string;
  /** Compact mode with smaller styling */
  compact?: boolean;
  /** Test ID for testing */
  testID?: string;
}

interface DeviceItemProps {
  device: WPDevice;
  isSelected: boolean;
  isDisabled: boolean;
  selectionMode: SelectionMode;
  onPress: () => void;
  compact: boolean;
}

function DeviceItem({
  device,
  isSelected,
  isDisabled,
  selectionMode,
  onPress,
  compact,
}: DeviceItemProps) {
  return (
    <TouchableOpacity
      style={[
        styles.deviceCard,
        compact && styles.deviceCardCompact,
        isSelected && styles.deviceCardSelected,
        isDisabled && styles.deviceCardDisabled,
      ]}
      onPress={onPress}
      disabled={isDisabled || selectionMode === 'none'}
      activeOpacity={0.7}
      testID={`device-item-${device.id}`}
    >
      {selectionMode !== 'none' && (
        <View style={styles.checkboxContainer}>
          <View
            style={[
              styles.checkbox,
              compact && styles.checkboxCompact,
              isSelected && styles.checkboxSelected,
              isDisabled && styles.checkboxDisabled,
            ]}
          >
            {isSelected && (
              <Ionicons
                name="checkmark"
                size={compact ? 12 : 16}
                color={AppColors.white}
              />
            )}
          </View>
        </View>
      )}

      <View style={styles.deviceInfo}>
        <View style={[styles.deviceIcon, compact && styles.deviceIconCompact]}>
          <Ionicons
            name="bluetooth"
            size={compact ? 18 : 24}
            color={isDisabled ? AppColors.textMuted : AppColors.primary}
          />
        </View>

        <View style={styles.deviceDetails}>
          <Text
            style={[
              styles.deviceName,
              compact && styles.deviceNameCompact,
              isDisabled && styles.deviceNameDisabled,
            ]}
            numberOfLines={1}
          >
            {device.name}
          </Text>

          {device.wellId && (
            <Text style={[styles.deviceMeta, compact && styles.deviceMetaCompact]}>
              Well ID: {device.wellId}
            </Text>
          )}

          <View style={styles.signalRow}>
            <WiFiSignalIndicator
              rssi={device.rssi}
              size={compact ? 'small' : 'small'}
            />
            <Text
              style={[
                styles.signalLabel,
                { color: getSignalStrengthColor(device.rssi) },
              ]}
            >
              {getSignalStrengthLabel(device.rssi)}
            </Text>
            <Text style={styles.signalDbm}>({device.rssi} dBm)</Text>
          </View>
        </View>
      </View>

      {isDisabled && (
        <View style={styles.disabledBadge}>
          <Text style={styles.disabledBadgeText}>Added</Text>
        </View>
      )}
    </TouchableOpacity>
  );
}

export function BLEScanner({
  onDevicesSelected,
  onDeviceSelected,
  selectionMode = 'multiple',
  autoScan = false,
  deviceFilter,
  disabledDeviceIds = new Set(),
  showInstructions = false,
  emptyStateMessage = 'No sensors found. Make sure your WP sensor is powered on and nearby.',
  compact = false,
  testID,
}: BLEScannerProps) {
  const {
    foundDevices,
    isScanning,
    isBLEAvailable,
    error,
    permissionError,
    scanDevices,
    stopScan,
    clearError,
  } = useBLE();

  const [selectedDevices, setSelectedDevices] = useState<Set<string>>(new Set());
  const [hasScanned, setHasScanned] = useState(false);

  // Filter devices if filter function provided
  const filteredDevices = deviceFilter
    ? foundDevices.filter(deviceFilter)
    : foundDevices;

  // Auto-scan on mount if enabled
  useEffect(() => {
    if (autoScan && !hasScanned) {
      handleScan();
    }
  }, [autoScan, hasScanned]);

  // Select all devices by default in multiple selection mode when scan completes
  useEffect(() => {
    if (
      selectionMode === 'multiple' &&
      filteredDevices.length > 0 &&
      !isScanning &&
      hasScanned
    ) {
      const selectableIds = filteredDevices
        .filter((d) => !disabledDeviceIds.has(d.id))
        .map((d) => d.id);
      setSelectedDevices(new Set(selectableIds));
    }
  }, [filteredDevices, isScanning, hasScanned, selectionMode, disabledDeviceIds]);

  // Notify parent of selection changes
  useEffect(() => {
    const selected = filteredDevices.filter((d) => selectedDevices.has(d.id));

    if (selectionMode === 'single' && selected.length === 1 && onDeviceSelected) {
      onDeviceSelected(selected[0]);
    }

    if (onDevicesSelected) {
      onDevicesSelected(selected);
    }
  }, [selectedDevices, filteredDevices, selectionMode, onDeviceSelected, onDevicesSelected]);

  const handleScan = useCallback(async () => {
    try {
      clearError();
      setHasScanned(true);
      setSelectedDevices(new Set());
      await scanDevices();
    } catch {
      // Error is handled by BLE context
    }
  }, [clearError, scanDevices]);

  const handleDevicePress = useCallback(
    (deviceId: string) => {
      if (selectionMode === 'none') return;

      if (selectionMode === 'single') {
        setSelectedDevices(new Set([deviceId]));
      } else {
        setSelectedDevices((prev) => {
          const next = new Set(prev);
          if (next.has(deviceId)) {
            next.delete(deviceId);
          } else {
            next.add(deviceId);
          }
          return next;
        });
      }
    },
    [selectionMode]
  );

  const toggleSelectAll = useCallback(() => {
    const selectableDevices = filteredDevices.filter(
      (d) => !disabledDeviceIds.has(d.id)
    );
    if (selectedDevices.size === selectableDevices.length) {
      setSelectedDevices(new Set());
    } else {
      setSelectedDevices(new Set(selectableDevices.map((d) => d.id)));
    }
  }, [filteredDevices, disabledDeviceIds, selectedDevices]);

  const handleOpenSettings = useCallback(() => {
    Linking.openSettings();
  }, []);

  const renderDevice = useCallback(
    ({ item }: { item: WPDevice }) => (
      <DeviceItem
        device={item}
        isSelected={selectedDevices.has(item.id)}
        isDisabled={disabledDeviceIds.has(item.id)}
        selectionMode={selectionMode}
        onPress={() => handleDevicePress(item.id)}
        compact={compact}
      />
    ),
    [selectedDevices, disabledDeviceIds, selectionMode, handleDevicePress, compact]
  );

  const keyExtractor = useCallback((item: WPDevice) => item.id, []);

  const selectableCount = filteredDevices.filter(
    (d) => !disabledDeviceIds.has(d.id)
  ).length;
  const allSelected = selectedDevices.size === selectableCount && selectableCount > 0;

  return (
    <View style={[styles.container, compact && styles.containerCompact]} testID={testID}>
      {/* Simulator Warning */}
      {!isBLEAvailable && (
        <View style={styles.simulatorWarning}>
          <Ionicons name="information-circle" size={16} color={AppColors.warning} />
          <Text style={styles.simulatorWarningText}>
            Simulator mode - showing mock sensors
          </Text>
        </View>
      )}

      {/* Permission Error */}
      {permissionError && error && (
        <View style={styles.permissionError}>
          <View style={styles.permissionErrorContent}>
            <Ionicons name="warning" size={18} color={AppColors.error} />
            <Text style={styles.permissionErrorText}>{error}</Text>
          </View>
          <TouchableOpacity
            style={styles.settingsButton}
            onPress={handleOpenSettings}
          >
            <Text style={styles.settingsButtonText}>Open Settings</Text>
            <Ionicons name="settings-outline" size={14} color={AppColors.error} />
          </TouchableOpacity>
        </View>
      )}

      {/* Instructions */}
      {showInstructions && !isScanning && filteredDevices.length === 0 && (
        <View style={[styles.instructionsCard, compact && styles.instructionsCardCompact]}>
          <Text style={styles.instructionsTitle}>Scanning for Sensors</Text>
          <View style={styles.instruction}>
            <Ionicons name="power" size={16} color={AppColors.textMuted} />
            <Text style={styles.instructionText}>
              Make sure sensors are powered on
            </Text>
          </View>
          <View style={styles.instruction}>
            <Ionicons name="locate" size={16} color={AppColors.textMuted} />
            <Text style={styles.instructionText}>
              Stay within 10 meters of sensors
            </Text>
          </View>
          <View style={styles.instruction}>
            <Ionicons name="bluetooth" size={16} color={AppColors.textMuted} />
            <Text style={styles.instructionText}>
              Bluetooth must be enabled
            </Text>
          </View>
        </View>
      )}

      {/* Scan Button (when not scanning and no devices) */}
      {!isScanning && filteredDevices.length === 0 && (
        <TouchableOpacity
          style={[styles.scanButton, compact && styles.scanButtonCompact]}
          onPress={handleScan}
          testID="scan-button"
        >
          <Ionicons name="bluetooth" size={compact ? 20 : 24} color={AppColors.white} />
          <Text style={[styles.scanButtonText, compact && styles.scanButtonTextCompact]}>
            Scan for Sensors
          </Text>
        </TouchableOpacity>
      )}

      {/* Scanning State */}
      {isScanning && (
        <View style={[styles.scanningCard, compact && styles.scanningCardCompact]}>
          <ActivityIndicator
            size={compact ? 'small' : 'large'}
            color={AppColors.primary}
          />
          <Text style={[styles.scanningText, compact && styles.scanningTextCompact]}>
            Scanning for WP sensors...
          </Text>
          <TouchableOpacity
            style={styles.stopScanButton}
            onPress={stopScan}
            testID="stop-scan-button"
          >
            <Text style={styles.stopScanText}>Stop Scan</Text>
          </TouchableOpacity>
        </View>
      )}

      {/* Device List Header */}
      {!isScanning && filteredDevices.length > 0 && (
        <View style={styles.listHeader}>
          <Text style={styles.listHeaderTitle}>
            Found Sensors ({filteredDevices.length})
          </Text>
          <View style={styles.listHeaderActions}>
            {selectionMode === 'multiple' && selectableCount > 0 && (
              <TouchableOpacity
                style={styles.selectAllButton}
                onPress={toggleSelectAll}
                testID="select-all-button"
              >
                <Ionicons
                  name={allSelected ? 'checkbox' : 'square-outline'}
                  size={16}
                  color={AppColors.primary}
                />
                <Text style={styles.selectAllText}>
                  {allSelected ? 'Deselect All' : 'Select All'}
                </Text>
              </TouchableOpacity>
            )}
            <TouchableOpacity
              style={styles.rescanButton}
              onPress={handleScan}
              testID="rescan-button"
            >
              <Ionicons name="refresh" size={16} color={AppColors.primary} />
              <Text style={styles.rescanText}>Rescan</Text>
            </TouchableOpacity>
          </View>
        </View>
      )}

      {/* Device List */}
      {!isScanning && filteredDevices.length > 0 && (
        <FlatList
          data={filteredDevices}
          renderItem={renderDevice}
          keyExtractor={keyExtractor}
          contentContainerStyle={styles.deviceList}
          showsVerticalScrollIndicator={false}
          testID="device-list"
        />
      )}

      {/* Empty State (after scan, no devices) */}
      {!isScanning && hasScanned && filteredDevices.length === 0 && !error && (
        <View style={[styles.emptyState, compact && styles.emptyStateCompact]}>
          <View style={styles.emptyIconContainer}>
            <Ionicons
              name="bluetooth-outline"
              size={compact ? 32 : 48}
              color={AppColors.textMuted}
            />
          </View>
          <Text style={[styles.emptyTitle, compact && styles.emptyTitleCompact]}>
            No Sensors Found
          </Text>
          <Text style={[styles.emptyText, compact && styles.emptyTextCompact]}>
            {emptyStateMessage}
          </Text>
          <TouchableOpacity
            style={[styles.retryButton, compact && styles.retryButtonCompact]}
            onPress={handleScan}
            testID="retry-scan-button"
          >
            <Ionicons name="refresh" size={18} color={AppColors.primary} />
            <Text style={styles.retryButtonText}>Try Again</Text>
          </TouchableOpacity>
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  containerCompact: {
    flex: 0,
  },

  // Simulator Warning
  simulatorWarning: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: AppColors.warningLight,
    paddingVertical: Spacing.xs,
    paddingHorizontal: Spacing.md,
    gap: Spacing.xs,
    borderRadius: BorderRadius.sm,
    marginBottom: Spacing.sm,
  },
  simulatorWarningText: {
    fontSize: FontSizes.xs,
    color: AppColors.warning,
    fontWeight: FontWeights.medium,
  },

  // Permission Error
  permissionError: {
    backgroundColor: AppColors.errorLight,
    padding: Spacing.md,
    borderRadius: BorderRadius.md,
    marginBottom: Spacing.md,
    gap: Spacing.sm,
  },
  permissionErrorContent: {
    flexDirection: 'row',
    alignItems: 'flex-start',
    gap: Spacing.xs,
  },
  permissionErrorText: {
    fontSize: FontSizes.sm,
    color: AppColors.error,
    fontWeight: FontWeights.medium,
    flex: 1,
    lineHeight: 18,
  },
  settingsButton: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: AppColors.white,
    paddingVertical: Spacing.xs,
    paddingHorizontal: Spacing.sm,
    borderRadius: BorderRadius.sm,
    gap: Spacing.xs,
    alignSelf: 'flex-start',
  },
  settingsButtonText: {
    fontSize: FontSizes.xs,
    fontWeight: FontWeights.semibold,
    color: AppColors.error,
  },

  // Instructions
  instructionsCard: {
    backgroundColor: AppColors.surface,
    borderRadius: BorderRadius.lg,
    padding: Spacing.md,
    marginBottom: Spacing.md,
    gap: Spacing.sm,
    ...Shadows.xs,
  },
  instructionsCardCompact: {
    padding: Spacing.sm,
    gap: Spacing.xs,
  },
  instructionsTitle: {
    fontSize: FontSizes.sm,
    fontWeight: FontWeights.semibold,
    color: AppColors.textPrimary,
    marginBottom: Spacing.xs,
  },
  instruction: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: Spacing.sm,
  },
  instructionText: {
    fontSize: FontSizes.sm,
    color: AppColors.textSecondary,
  },

  // Scan Button
  scanButton: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: AppColors.primary,
    paddingVertical: Spacing.md,
    borderRadius: BorderRadius.lg,
    gap: Spacing.sm,
    ...Shadows.md,
  },
  scanButtonCompact: {
    paddingVertical: Spacing.sm,
  },
  scanButtonText: {
    fontSize: FontSizes.base,
    fontWeight: FontWeights.semibold,
    color: AppColors.white,
  },
  scanButtonTextCompact: {
    fontSize: FontSizes.sm,
  },

  // Scanning State
  scanningCard: {
    backgroundColor: AppColors.surface,
    borderRadius: BorderRadius.lg,
    padding: Spacing.xl,
    alignItems: 'center',
    ...Shadows.sm,
  },
  scanningCardCompact: {
    padding: Spacing.md,
  },
  scanningText: {
    fontSize: FontSizes.base,
    color: AppColors.textSecondary,
    marginTop: Spacing.md,
    marginBottom: Spacing.sm,
  },
  scanningTextCompact: {
    fontSize: FontSizes.sm,
    marginTop: Spacing.sm,
  },
  stopScanButton: {
    paddingVertical: Spacing.xs,
    paddingHorizontal: Spacing.md,
  },
  stopScanText: {
    fontSize: FontSizes.sm,
    fontWeight: FontWeights.medium,
    color: AppColors.error,
  },

  // List Header
  listHeader: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginBottom: Spacing.sm,
  },
  listHeaderTitle: {
    fontSize: FontSizes.sm,
    fontWeight: FontWeights.semibold,
    color: AppColors.textSecondary,
    textTransform: 'uppercase',
    letterSpacing: 0.5,
  },
  listHeaderActions: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: Spacing.md,
  },
  selectAllButton: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 4,
  },
  selectAllText: {
    fontSize: FontSizes.sm,
    fontWeight: FontWeights.medium,
    color: AppColors.primary,
  },
  rescanButton: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 4,
  },
  rescanText: {
    fontSize: FontSizes.sm,
    fontWeight: FontWeights.medium,
    color: AppColors.primary,
  },

  // Device List
  deviceList: {
    gap: Spacing.sm,
  },

  // Device Card
  deviceCard: {
    backgroundColor: AppColors.surface,
    borderRadius: BorderRadius.lg,
    padding: Spacing.md,
    flexDirection: 'row',
    alignItems: 'center',
    ...Shadows.xs,
  },
  deviceCardCompact: {
    padding: Spacing.sm,
  },
  deviceCardSelected: {
    borderWidth: 2,
    borderColor: AppColors.primary,
  },
  deviceCardDisabled: {
    opacity: 0.6,
  },

  // Checkbox
  checkboxContainer: {
    marginRight: Spacing.sm,
  },
  checkbox: {
    width: 24,
    height: 24,
    borderRadius: BorderRadius.sm,
    borderWidth: 2,
    borderColor: AppColors.border,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: AppColors.white,
  },
  checkboxCompact: {
    width: 20,
    height: 20,
  },
  checkboxSelected: {
    backgroundColor: AppColors.primary,
    borderColor: AppColors.primary,
  },
  checkboxDisabled: {
    backgroundColor: AppColors.surfaceSecondary,
    borderColor: AppColors.border,
  },

  // Device Info
  deviceInfo: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    gap: Spacing.md,
  },
  deviceIcon: {
    width: 48,
    height: 48,
    borderRadius: BorderRadius.lg,
    backgroundColor: AppColors.primaryLighter,
    justifyContent: 'center',
    alignItems: 'center',
  },
  deviceIconCompact: {
    width: 36,
    height: 36,
  },
  deviceDetails: {
    flex: 1,
  },
  deviceName: {
    fontSize: FontSizes.base,
    fontWeight: FontWeights.semibold,
    color: AppColors.textPrimary,
    marginBottom: 2,
  },
  deviceNameCompact: {
    fontSize: FontSizes.sm,
  },
  deviceNameDisabled: {
    color: AppColors.textMuted,
  },
  deviceMeta: {
    fontSize: FontSizes.xs,
    color: AppColors.textMuted,
    marginBottom: 4,
  },
  deviceMetaCompact: {
    marginBottom: 2,
  },
  signalRow: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 6,
  },
  signalLabel: {
    fontSize: FontSizes.xs,
    fontWeight: FontWeights.semibold,
  },
  signalDbm: {
    fontSize: FontSizes.xs,
    color: AppColors.textMuted,
  },

  // Disabled Badge
  disabledBadge: {
    backgroundColor: AppColors.successLight,
    paddingVertical: Spacing.xs,
    paddingHorizontal: Spacing.sm,
    borderRadius: BorderRadius.sm,
  },
  disabledBadgeText: {
    fontSize: FontSizes.xs,
    fontWeight: FontWeights.medium,
    color: AppColors.success,
  },

  // Empty State
  emptyState: {
    alignItems: 'center',
    padding: Spacing.xl,
    backgroundColor: AppColors.surface,
    borderRadius: BorderRadius.lg,
    ...Shadows.sm,
  },
  emptyStateCompact: {
    padding: Spacing.md,
  },
  emptyIconContainer: {
    width: 80,
    height: 80,
    borderRadius: 40,
    backgroundColor: AppColors.surfaceSecondary,
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom: Spacing.md,
  },
  emptyTitle: {
    fontSize: FontSizes.lg,
    fontWeight: FontWeights.semibold,
    color: AppColors.textPrimary,
    marginBottom: Spacing.xs,
  },
  emptyTitleCompact: {
    fontSize: FontSizes.base,
  },
  emptyText: {
    fontSize: FontSizes.sm,
    color: AppColors.textMuted,
    textAlign: 'center',
    lineHeight: 20,
    marginBottom: Spacing.md,
  },
  emptyTextCompact: {
    fontSize: FontSizes.xs,
  },
  retryButton: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: Spacing.xs,
    paddingVertical: Spacing.sm,
    paddingHorizontal: Spacing.md,
    borderRadius: BorderRadius.md,
    borderWidth: 1,
    borderColor: AppColors.primary,
  },
  retryButtonCompact: {
    paddingVertical: Spacing.xs,
    paddingHorizontal: Spacing.sm,
  },
  retryButtonText: {
    fontSize: FontSizes.sm,
    fontWeight: FontWeights.medium,
    color: AppColors.primary,
  },
});

export default BLEScanner;
