import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
import 'package:syncrow_app/features/auth/model/project_model.dart';

import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_event.dart';
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';

import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/services/api/home_management_api.dart';
import 'package:syncrow_app/utils/constants/temp_const.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';

class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
  DeviceManagerBloc() : super(DeviceManagerState.initial()) {
    on<FetchAllDevices>(_onFetchAllDevices);
    on<FetchDevicesByRoomId>(_onFetchDevicesByRoomId);
    on<SelectCategory>(_onSelectCategory);
    on<UnselectAllCategories>(_onUnselectAllCategories);
    on<SelectDevice>(_onSelectDevice);
    on<ChangeCategorySwitchValue>(_onChangeCategorySwitchValue);
    on<TurnOnOffDevice>(_onTurnOnOffDevice);
    on<ClearCategoriesSelection>(_onClearCategoriesSelection);
    on<DeviceFunctionsEvent>(_getDeviceFunctions);
  }

  static List<DevicesCategoryModel>? allCategories;

  Future<void> _onFetchAllDevices(
      FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
    emit(state.copyWith(loading: true));
    try {
      Project? project = HomeCubit.getInstance().project;

      final allDevices = await HomeManagementAPI.fetchDevicesByUnitId(
          project?.uuid ?? TempConst.projectIdDev);
      emit(state.copyWith(
          devices: _getOnlyImplementedDevices(allDevices), loading: false));
    } catch (e) {
      emit(state.copyWith(error: e.toString(), loading: false));
    }
  }

  Future<void> _onFetchDevicesByRoomId(
      FetchDevicesByRoomId event, Emitter<DeviceManagerState> emit) async {
    emit(state.copyWith(loading: true));
    try {
      Project? project = HomeCubit.getInstance().project;

      final devices = await DevicesAPI.getDevicesByRoomId(
          communityUuid: event.unit.community.uuid,
          spaceUuid: event.unit.id,
          roomId: event.roomId,
          projectId: project?.uuid ?? TempConst.projectIdDev);

      emit(state.copyWith(
          devices: _getOnlyImplementedDevices(devices), loading: false));
    } catch (e) {
      emit(state.copyWith(error: e.toString(), loading: false));
    }
  }

  void _onSelectCategory(
      SelectCategory event, Emitter<DeviceManagerState> emit) {
    for (var i = 0; i < allCategories!.length; i++) {
      allCategories![i].isSelected = i == event.index;
    }
    emit(state.copyWith(categoryChanged: true));
  }

  void _onUnselectAllCategories(
      UnselectAllCategories event, Emitter<DeviceManagerState> emit) {
    for (var category in allCategories!) {
      category.isSelected = false;
    }
    emit(state.copyWith(categoryChanged: true));
  }

  void _onSelectDevice(SelectDevice event, Emitter<DeviceManagerState> emit) {
    for (var category in allCategories!) {
      if (category.devices != null) {
        for (var device in category.devices!) {
          if (device.isSelected) {
            category.isSelected = false;
            emit(state.copyWith(deviceSelected: true));
            return;
          }
        }
      }
    }
    event.device.isSelected = !event.device.isSelected;
    emit(state.copyWith(deviceSelected: true));
  }

  void _onChangeCategorySwitchValue(
      ChangeCategorySwitchValue event, Emitter<DeviceManagerState> emit) {
    var category = event.category;
    if (category.devicesStatus != null) {
      category.devicesStatus = !category.devicesStatus!;
      if (category.devices != null) {
        for (var device in category.devices!) {
          device.isOnline = category.devicesStatus;
        }
      }
    } else {
      category.devicesStatus = true;
      if (category.devices != null) {
        for (var device in category.devices!) {
          device.isOnline = true;
        }
      }
    }
    _updateDevicesStatus(category, emit);
  }

  void _onTurnOnOffDevice(
      TurnOnOffDevice event, Emitter<DeviceManagerState> emit) {
    var device = event.device;
    device.isOnline = !device.isOnline!;
    DevicesCategoryModel category = allCategories!.firstWhere((category) {
      return category.devices != null && category.devices!.contains(device);
    });
    _updateDevicesStatus(category, emit);
  }

  void _onClearCategoriesSelection(
      ClearCategoriesSelection event, Emitter<DeviceManagerState> emit) {
    for (var category in allCategories!) {
      category.isSelected = false;
      if (category.devices != null) {
        for (var device in category.devices!) {
          device.isSelected = false;
        }
      }
    }
    Navigator.popUntil(event.context, (route) => route.isFirst);
    emit(state.copyWith(categoryChanged: true)); // Set category changed state
  }

  void _updateDevicesStatus(
      DevicesCategoryModel category, Emitter<DeviceManagerState> emit) {
    if (category.devices != null && category.devices!.isNotEmpty) {
      bool? tempStatus = category.devices![0].isOnline;
      for (var device in category.devices!) {
        if (device.isOnline != tempStatus) {
          category.devicesStatus = null;
          break;
        }
        category.devicesStatus = tempStatus;
      }
      emit(state.copyWith(categoryChanged: true));
    }
  }

  Future<void> _getDeviceFunctions(
      DeviceFunctionsEvent event, Emitter<DeviceManagerState> emit) async {
    emit(state.copyWith(functionsLoading: true));
    try {
      final deviceFunctions = await DevicesAPI.deviceFunctions(event.deviceId);

      emit(state.copyWith(
          functionsLoading: false, deviceFunctions: deviceFunctions));
    } catch (e) {
      emit(state.copyWith(functionsLoading: false, error: e.toString()));
    }
  }

  List<DeviceModel> _getOnlyImplementedDevices(List<DeviceModel> devices) {
    const allowedDeviceTypes = {
      DeviceType.AC,
      DeviceType.DoorLock,
      DeviceType.Gateway,
      DeviceType.WallSensor,
      DeviceType.CeilingSensor,
      DeviceType.ThreeGang,
      DeviceType.OneGang,
      DeviceType.TwoGang,
      DeviceType.WH,
      DeviceType.FlushMountedSensor,
    };

    return devices
        .where((device) => allowedDeviceTypes.contains(device.productType))
        .toList();
  }
}
