import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/services/devices_mang_api.dart';

part 'device_managment_event.dart';
part 'device_managment_state.dart';

class DeviceManagementBloc
    extends Bloc<DeviceManagementEvent, DeviceManagementState> {
  int _selectedIndex = 0;
  List<AllDevicesModel> _devices = [];
  int _onlineCount = 0;
  int _offlineCount = 0;
  int _lowBatteryCount = 0;
  final List<AllDevicesModel> _selectedDevices = [];
  List<AllDevicesModel> _filteredDevices = [];
  String currentProductName = '';
  String? currentCommunity;
  String? currentUnitName;
  String subSpaceName = '';

  DeviceManagementBloc() : super(DeviceManagementInitial()) {
    on<FetchDevices>(_onFetchDevices);
    on<FilterDevices>(_onFilterDevices);
    on<SelectedFilterChanged>(_onSelectedFilterChanged);
    on<SearchDevices>(_onSearchDevices);
    on<SelectDevice>(_onSelectDevice);
    on<ResetFilters>(_onResetFilters);
    on<ResetSelectedDevices>(_onResetSelectedDevices);
    on<UpdateSelection>(_onUpdateSelection);
    on<UpdateDeviceName>(_onUpdateDeviceName);
    on<UpdateSubSpaceName>(_onUpdateSubSpaceName);
  }

  Future<void> _onFetchDevices(
      FetchDevices event, Emitter<DeviceManagementState> emit) async {
    emit(DeviceManagementLoading());
    try {
      var devices = <AllDevicesModel>[];
      _devices.clear();
      final spaceBloc = event.context.read<SpaceTreeBloc>();
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';

      if (spaceBloc.state.selectedCommunities.isEmpty) {
        devices = await DevicesManagementApi().fetchDevices('', '', projectUuid);
      } else {
        for (final community in spaceBloc.state.selectedCommunities) {
          final spacesList =
              spaceBloc.state.selectedCommunityAndSpaces[community] ?? [];
          for (final space in spacesList) {
            devices.addAll(await DevicesManagementApi()
                .fetchDevices(community, space, projectUuid));
          }
        }
      }

      _selectedDevices.clear();
      _devices = devices;
      _filteredDevices = devices;
      _calculateDeviceCounts();
      emit(DeviceManagementLoaded(
        devices: devices,
        selectedIndex: 0,
        onlineCount: _onlineCount,
        offlineCount: _offlineCount,
        lowBatteryCount: _lowBatteryCount,
        selectedDevice: null,
        isControlButtonEnabled: false,
      ));
    } catch (e) {
      emit(DeviceManagementInitial());
    }
  }

  Future<void> _onFilterDevices(
      FilterDevices event, Emitter<DeviceManagementState> emit) async {
    if (_devices.isNotEmpty) {
      _filteredDevices = List.from(_devices.where((device) {
        switch (event.filter) {
          case 'Online':
            return device.online == true;
          case 'Offline':
            return device.online == false;
          case 'Low Battery':
            return device.batteryLevel != null && device.batteryLevel! < 20;
          default:
            return true;
        }
      }).toList());

      emit(DeviceManagementFiltered(
        filteredDevices: _filteredDevices,
        selectedIndex: _selectedIndex,
        onlineCount: _onlineCount,
        offlineCount: _offlineCount,
        lowBatteryCount: _lowBatteryCount,
        selectedDevice: _selectedDevices.isNotEmpty ? _selectedDevices : null,
        isControlButtonEnabled: _selectedDevices.isNotEmpty,
      ));

      if (currentProductName.isNotEmpty) {
        add(SearchDevices(deviceNameOrProductName: currentProductName));
      }
    }
  }

  Future<void> _onResetFilters(
      ResetFilters event, Emitter<DeviceManagementState> emit) async {
    currentProductName = '';
    _selectedDevices.clear();
    _filteredDevices = List.from(_devices);
    _selectedIndex = 0;
    emit(DeviceManagementLoaded(
      devices: _devices,
      selectedIndex: 0,
      onlineCount: _onlineCount,
      offlineCount: _offlineCount,
      lowBatteryCount: _lowBatteryCount,
      selectedDevice: null,
      isControlButtonEnabled: false,
    ));
  }

  void _onResetSelectedDevices(
      ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
    _selectedDevices.clear();

    if (state is DeviceManagementLoaded) {
      emit(DeviceManagementLoaded(
        devices: _devices,
        selectedIndex: _selectedIndex,
        onlineCount: _onlineCount,
        offlineCount: _offlineCount,
        lowBatteryCount: _lowBatteryCount,
        selectedDevice: null,
        isControlButtonEnabled: false,
      ));
    } else if (state is DeviceManagementFiltered) {
      emit(DeviceManagementFiltered(
        filteredDevices: (state as DeviceManagementFiltered).filteredDevices,
        selectedIndex: _selectedIndex,
        onlineCount: _onlineCount,
        offlineCount: _offlineCount,
        lowBatteryCount: _lowBatteryCount,
        selectedDevice: null,
        isControlButtonEnabled: false,
      ));
    }
  }

  void _onSelectedFilterChanged(
      SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
    _selectedIndex = event.selectedIndex;
    add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
  }

  void _onSelectDevice(SelectDevice event, Emitter<DeviceManagementState> emit) {
    final selectedUuid = event.selectedDevice.uuid;

    if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
      _selectedDevices.removeWhere((device) => device.uuid == selectedUuid);
    } else {
      _selectedDevices.add(event.selectedDevice);
    }

    final clonedSelectedDevices = List<AllDevicesModel>.from(_selectedDevices);

    final isControlButtonEnabled =
        _checkIfControlButtonEnabled(clonedSelectedDevices);

    if (state is DeviceManagementLoaded) {
      emit(DeviceManagementLoaded(
        devices: _devices,
        selectedIndex: _selectedIndex,
        onlineCount: _onlineCount,
        offlineCount: _offlineCount,
        lowBatteryCount: _lowBatteryCount,
        selectedDevice:
            clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
        isControlButtonEnabled: isControlButtonEnabled,
      ));
    } else if (state is DeviceManagementFiltered) {
      emit(DeviceManagementFiltered(
        filteredDevices: (state as DeviceManagementFiltered).filteredDevices,
        selectedIndex: _selectedIndex,
        onlineCount: _onlineCount,
        offlineCount: _offlineCount,
        lowBatteryCount: _lowBatteryCount,
        selectedDevice:
            clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
        isControlButtonEnabled: isControlButtonEnabled,
      ));
    }
  }

  void _onUpdateSelection(
      UpdateSelection event, Emitter<DeviceManagementState> emit) {
    final selectedDevices = <AllDevicesModel>[];
    var devicesToSelectFrom = <AllDevicesModel>[];

    if (state is DeviceManagementLoaded) {
      devicesToSelectFrom = (state as DeviceManagementLoaded).devices;
    } else if (state is DeviceManagementFiltered) {
      devicesToSelectFrom = (state as DeviceManagementFiltered).filteredDevices;
    }

    for (var i = 0; i < event.selectedRows.length; i++) {
      if (event.selectedRows[i]) {
        selectedDevices.add(devicesToSelectFrom[i]);
      }
    }

    if (state is DeviceManagementLoaded) {
      final loadedState = state as DeviceManagementLoaded;
      emit(DeviceManagementLoaded(
        devices: loadedState.devices,
        selectedIndex: loadedState.selectedIndex,
        onlineCount: loadedState.onlineCount,
        offlineCount: loadedState.offlineCount,
        lowBatteryCount: loadedState.lowBatteryCount,
        selectedDevice: selectedDevices,
        isControlButtonEnabled: _checkIfControlButtonEnabled(selectedDevices),
      ));
    } else if (state is DeviceManagementFiltered) {
      final filteredState = state as DeviceManagementFiltered;
      emit(DeviceManagementFiltered(
        filteredDevices: filteredState.filteredDevices,
        selectedIndex: filteredState.selectedIndex,
        onlineCount: filteredState.onlineCount,
        offlineCount: filteredState.offlineCount,
        lowBatteryCount: filteredState.lowBatteryCount,
        selectedDevice: selectedDevices,
        isControlButtonEnabled: _checkIfControlButtonEnabled(selectedDevices),
      ));
    }
  }

  bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
    if (selectedDevices.length > 1) {
      final productTypes =
          selectedDevices.map((device) => device.productType).toSet();
      return productTypes.length == 1;
    } else if (selectedDevices.length == 1) {
      return true;
    }
    return false;
  }

  void _calculateDeviceCounts() {
    _onlineCount = _devices.where((device) => device.online == true).length;
    _offlineCount = _devices.where((device) => device.online == false).length;
    _lowBatteryCount = _devices
        .where((device) => device.batteryLevel != null && device.batteryLevel! < 20)
        .length;
  }

  String _getFilterFromIndex(int index) {
    switch (index) {
      case 1:
        return 'Online';
      case 2:
        return 'Offline';
      case 3:
        return 'Low Battery';
      default:
        return 'All';
    }
  }

  void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) {
    if ((event.community == null || event.community!.isEmpty) &&
        (event.unitName == null || event.unitName!.isEmpty) &&
        (event.deviceNameOrProductName == null ||
            event.deviceNameOrProductName!.isEmpty)) {
      currentProductName = '';
      _filteredDevices = List.from(_devices);
      emit(DeviceManagementLoaded(
        devices: _devices,
        selectedIndex: _selectedIndex,
        onlineCount: _onlineCount,
        offlineCount: _offlineCount,
        lowBatteryCount: _lowBatteryCount,
        selectedDevice: null,
        isControlButtonEnabled: false,
      ));
      return;
    }
    if (event.deviceNameOrProductName == currentProductName &&
        event.community == currentCommunity &&
        event.unitName == currentUnitName &&
        event.searchField) {
      return;
    }

    currentProductName = event.deviceNameOrProductName ?? '';
    currentCommunity = event.community;
    currentUnitName = event.unitName;

    final devicesToSearch = _devices;

    if (devicesToSearch.isNotEmpty) {
      final searchText = event.deviceNameOrProductName?.toLowerCase() ?? '';

      final filteredDevices = devicesToSearch.where((device) {
        final matchesCommunity = event.community == null ||
            event.community!.isEmpty ||
            (device.community?.name
                    ?.toLowerCase()
                    .contains(event.community!.toLowerCase()) ??
                false);

        final matchesUnit = event.unitName == null ||
            event.unitName!.isEmpty ||
            (device.spaces != null &&
                device.spaces!.any((space) =>
                    space.spaceName != null &&
                    space.spaceName!
                        .toLowerCase()
                        .contains(event.unitName!.toLowerCase())));

        final matchesSearchText = searchText.isEmpty ||
            (device.name?.toLowerCase().contains(searchText) ?? false) ||
            (device.productName?.toLowerCase().contains(searchText) ?? false);

        return matchesCommunity && matchesUnit && matchesSearchText;
      }).toList();

      _filteredDevices = filteredDevices;

      emit(DeviceManagementFiltered(
        filteredDevices: filteredDevices,
        selectedIndex: _selectedIndex,
        onlineCount: _onlineCount,
        offlineCount: _offlineCount,
        lowBatteryCount: _lowBatteryCount,
        selectedDevice: null,
        isControlButtonEnabled: false,
      ));
    }
  }

  void _onUpdateDeviceName(
      UpdateDeviceName event, Emitter<DeviceManagementState> emit) {
    final devices = _devices.map((device) {
      if (device.uuid == event.deviceId) {
        final modifiedDevice = device.copyWith(name: event.newName);
        _selectedDevices.removeWhere((device) => device.uuid == event.deviceId);
        _selectedDevices.add(modifiedDevice);
        return modifiedDevice;
      }
      return device;
    }).toList();

    final filteredDevices = _filteredDevices.map((device) {
      if (device.uuid == event.deviceId) {
        final modifiedDevice = device.copyWith(name: event.newName);
        _selectedDevices.removeWhere((device) => device.uuid == event.deviceId);
        _selectedDevices.add(modifiedDevice);
        return modifiedDevice;
      }
      return device;
    }).toList();

    _devices = devices;
    _filteredDevices = filteredDevices;

    if (state is DeviceManagementLoaded) {
      final loaded = state as DeviceManagementLoaded;
      final selectedDevices01 = _selectedDevices.map((device) {
        if (device.uuid == event.deviceId) {
          final modifiedDevice = device.copyWith(name: event.newName);
          return modifiedDevice;
        }
        return device;
      }).toList();
      emit(DeviceManagementLoaded(
        devices: devices,
        selectedIndex: loaded.selectedIndex,
        onlineCount: loaded.onlineCount,
        offlineCount: loaded.offlineCount,
        lowBatteryCount: loaded.lowBatteryCount,
        selectedDevice: selectedDevices01,
        isControlButtonEnabled: loaded.isControlButtonEnabled,
      ));
    } else if (state is DeviceManagementFiltered) {
      final filtered = state as DeviceManagementFiltered;
      final selectedDevices01 = filtered.selectedDevice?.map((device) {
        if (device.uuid == event.deviceId) {
          final modifiedDevice = device.copyWith(name: event.newName);
          return modifiedDevice;
        }
        return device;
      }).toList();
      emit(DeviceManagementFiltered(
        filteredDevices: filteredDevices,
        selectedIndex: filtered.selectedIndex,
        onlineCount: filtered.onlineCount,
        offlineCount: filtered.offlineCount,
        lowBatteryCount: filtered.lowBatteryCount,
        selectedDevice: selectedDevices01,
        isControlButtonEnabled: filtered.isControlButtonEnabled,
      ));
    }
  }

  void _onUpdateSubSpaceName(
      UpdateSubSpaceName event, Emitter<DeviceManagementState> emit) {
    final devices = _devices.map((device) {
      if (device.uuid == event.deviceId) {
        return device.copyWith(
            subspace:
                device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
      }
      return device;
    }).toList();

    final filteredDevices = _filteredDevices.map((device) {
      if (device.uuid == event.deviceId) {
        return device.copyWith(
            subspace:
                device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
      }
      return device;
    }).toList();

    _devices = devices;
    _filteredDevices = filteredDevices;

    if (state is DeviceManagementLoaded) {
      final loaded = state as DeviceManagementLoaded;
      final selectedDevices = loaded.selectedDevice?.map((device) {
        if (device.uuid == event.deviceId) {
          return device.copyWith(
              subspace:
                  device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
        }
        return device;
      }).toList();
      emit(DeviceManagementLoaded(
        devices: _devices,
        selectedIndex: loaded.selectedIndex,
        onlineCount: loaded.onlineCount,
        offlineCount: loaded.offlineCount,
        lowBatteryCount: loaded.lowBatteryCount,
        selectedDevice: selectedDevices,
        isControlButtonEnabled: loaded.isControlButtonEnabled,
      ));
    } else if (state is DeviceManagementFiltered) {
      // final filtered = state as DeviceManagementFiltered;
      // emit(DeviceManagementFiltered(
      //   filteredDevices: _filteredDevices,
      //   selectedIndex: filtered.selectedIndex,
      //   onlineCount: filtered.onlineCount,
      //   offlineCount: filtered.offlineCount,
      //   lowBatteryCount: filtered.lowBatteryCount,
      //   selectedDevice: filtered.selectedDevice,
      //   isControlButtonEnabled: filtered.isControlButtonEnabled,
      // ));
    }
  }

  void changeSubspaceName(
      String deviceId, String newSubSpaceName, String subspaceId) {
    add(UpdateSubSpaceName(
      deviceId: deviceId,
      newSubSpaceName: newSubSpaceName,
      subspaceId: subspaceId,
    ));
  }

  List<AllDevicesModel> get selectedDevices => _selectedDevices;
}
