import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:dio/dio.dart';
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/routines/bloc/automation_scene_trigger_bloc/automation_status_update.dart';
import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart';
import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart';
import 'package:syncrow_web/pages/routines/models/delay/delay_fucntions.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/models/routine_details_model.dart';
import 'package:syncrow_web/pages/routines/models/routine_model.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/devices_mang_api.dart';
import 'package:syncrow_web/services/routines_api.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/navigation_service.dart';
import 'package:syncrow_web/utils/snack_bar.dart';
import 'package:uuid/uuid.dart';

part 'routine_event.dart';
part 'routine_state.dart';

class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
  RoutineBloc() : super(const RoutineState()) {
    on<AddToIfContainer>(_onAddToIfContainer);
    on<AddToThenContainer>(_onAddToThenContainer);
    on<LoadScenes>(_onLoadScenes);
    on<LoadAutomation>(_onLoadAutomation);
    on<AddFunctionToRoutine>(_onAddFunctionsToRoutine);
    on<SearchRoutines>(_onSearchRoutines);
    on<AddSelectedIcon>(_onAddSelectedIcon);
    on<CreateSceneEvent>(_onCreateScene);
    on<RemoveDragCard>(_onRemoveDragCard);
    on<ChangeAutomationOperator>(_changeOperatorOperator);
    on<EffectiveTimePeriodEvent>(_onEffectiveTimeEvent);
    on<CreateAutomationEvent>(_onCreateAutomation);
    on<SetRoutineName>(_onSetRoutineName);
    on<ResetRoutineState>(_onResetRoutineState);
    on<GetSceneDetails>(_onGetSceneDetails);
    on<GetAutomationDetails>(_onGetAutomationDetails);
    on<DeleteScene>(_deleteScene);
    // on<DeleteAutomation>(_deleteAutomation);
    on<FetchDevicesInRoutine>(_fetchDevices);
    on<UpdateScene>(_onUpdateScene);
    on<UpdateAutomation>(_onUpdateAutomation);
    on<TriggerSwitchTabsEvent>(_triggerSwitchTabsEvent);
    on<CreateNewRoutineViewEvent>(_createNewRoutineViewEvent);
    on<ResetErrorMessage>(_resetErrorMessage);
    on<SceneTrigger>(_onSceneTrigger);
    on<UpdateAutomationStatus>(_onUpdateAutomationStatus);
  }
  String selectedSpaceId = '';
  String selectedCommunityId = '';

  FutureOr<void> _triggerSwitchTabsEvent(
    TriggerSwitchTabsEvent event,
    Emitter<RoutineState> emit,
  ) {
    emit(state.copyWith(
        routineTab: event.isRoutineTab, createRoutineView: false));
    add(ResetRoutineState());
    if (event.isRoutineTab) {
      add(const LoadScenes());
      add(const LoadAutomation());
    }
  }

  _resetErrorMessage(
    ResetErrorMessage event,
    Emitter<RoutineState> emit,
  ) {
    emit(state.copyWith(errorMessage: ''));
  }

  FutureOr<void> _createNewRoutineViewEvent(
    CreateNewRoutineViewEvent event,
    Emitter<RoutineState> emit,
  ) {
    emit(state.copyWith(createRoutineView: event.createRoutineView));
  }

  void _onAddToIfContainer(AddToIfContainer event, Emitter<RoutineState> emit) {
    final updatedIfItems = List<Map<String, dynamic>>.from(state.ifItems);

    // Find the index of the item in teh current itemsList
    int index = updatedIfItems.indexWhere(
        (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
    // Replace the map if the index is valid
    if (index != -1) {
      updatedIfItems[index] = event.item;
    } else {
      updatedIfItems.add(event.item);
    }

    if (event.isTabToRun) {
      emit(state.copyWith(
          ifItems: updatedIfItems, isTabToRun: true, isAutomation: false));
    } else {
      emit(state.copyWith(
          ifItems: updatedIfItems, isTabToRun: false, isAutomation: true));
    }
  }

  void _onAddToThenContainer(
      AddToThenContainer event, Emitter<RoutineState> emit) {
    final currentItems = List<Map<String, dynamic>>.from(state.thenItems);

    // Find the index of the item in teh current itemsList
    int index = currentItems.indexWhere(
        (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']);
    // Replace the map if the index is valid
    if (index != -1) {
      currentItems[index] = event.item;
    } else {
      currentItems.add(event.item);
    }

    emit(state.copyWith(thenItems: currentItems));
  }

  void _onAddFunctionsToRoutine(
      AddFunctionToRoutine event, Emitter<RoutineState> emit) {
    try {
      if (event.functions.isEmpty) return;

      // List<DeviceFunctionData> selectedFunction = List<DeviceFunctionData>.from(event.functions);

      Map<String, List<DeviceFunctionData>> currentSelectedFunctions =
          Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);

      // if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) {
      //   List<DeviceFunctionData> currentFunctions =
      //       List<DeviceFunctionData>.from(currentSelectedFunctions[event.uniqueCustomId] ?? []);

      //   List<String> functionCode = [];
      //   for (int i = 0; i < selectedFunction.length; i++) {
      //     for (int j = 0; j < currentFunctions.length; j++) {
      //       if (selectedFunction[i].functionCode == currentFunctions[j].functionCode) {
      //         currentFunctions[j] = selectedFunction[i];
      //         if (!functionCode.contains(currentFunctions[j].functionCode)) {
      //           functionCode.add(currentFunctions[j].functionCode);
      //         }
      //       }
      //     }
      //   }

      //   for (int i = 0; i < functionCode.length; i++) {
      //     selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]);
      //   }

      //   currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions)
      //     ..addAll(selectedFunction);
      // } else {
      //   currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions);
      // }

      currentSelectedFunctions[event.uniqueCustomId] =
          List.from(event.functions);

      emit(state.copyWith(selectedFunctions: currentSelectedFunctions));
    } catch (e) {
      debugPrint('Error adding functions: $e');
    }
  }

Future<void> _onLoadScenes(
    LoadScenes event, Emitter<RoutineState> emit) async {
  emit(state.copyWith(isLoading: true, errorMessage: null));
  List<ScenesModel> scenes = [];
  try {
    BuildContext context = NavigationService.navigatorKey.currentContext!;
    var createRoutineBloc = context.read<CreateRoutineBloc>();
    final projectUuid = await ProjectManager.getProjectUUID() ?? '';
    if (createRoutineBloc.selectedSpaceId == '' &&
        createRoutineBloc.selectedCommunityId == '') {
      var spaceBloc = context.read<SpaceTreeBloc>();
      for (var communityId in spaceBloc.state.selectedCommunities) {
        List<String> spacesList =
            spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
        for (var spaceId in spacesList) {
          scenes.addAll(
              await SceneApi.getScenes(spaceId, communityId, projectUuid));
        }
      }
    } else {
      scenes.addAll(await SceneApi.getScenes(
          createRoutineBloc.selectedSpaceId,
          createRoutineBloc.selectedCommunityId,
          projectUuid));
    }

    emit(state.copyWith(
      scenes: scenes,
      isLoading: false,
    ));
  } catch (e) {
    emit(state.copyWith(
        isLoading: false,
        loadScenesErrorMessage: 'Failed to load scenes',
        errorMessage: '',
        loadAutomationErrorMessage: '',
        scenes: scenes));
  }
} 

  Future<void> _onLoadAutomation(
      LoadAutomation event, Emitter<RoutineState> emit) async {
    emit(state.copyWith(isLoading: true, errorMessage: null));
    List<ScenesModel> automations = [];
    final projectId = await ProjectManager.getProjectUUID() ?? '';

    BuildContext context = NavigationService.navigatorKey.currentContext!;
    var createRoutineBloc = context.read<CreateRoutineBloc>();
    try {
      if (createRoutineBloc.selectedSpaceId == '' &&
          createRoutineBloc.selectedCommunityId == '') {
        var spaceBloc = context.read<SpaceTreeBloc>();
        for (var communityId in spaceBloc.state.selectedCommunities) {
          List<String> spacesList =
              spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
          for (var spaceId in spacesList) {
            automations.addAll(
                await SceneApi.getAutomation(spaceId, communityId, projectId));
          }
        }
      } else {
        automations.addAll(await SceneApi.getAutomation(
            createRoutineBloc.selectedSpaceId,
            createRoutineBloc.selectedCommunityId,
            projectId));
      }
      emit(state.copyWith(
        automations: automations,
        isLoading: false,
      ));
    } catch (e) {
      emit(state.copyWith(
          isLoading: false,
          loadAutomationErrorMessage: 'Failed to load automations',
          errorMessage: '',
          loadScenesErrorMessage: '',
          automations: automations));
    }
  }

  FutureOr<void> _onSearchRoutines(
      SearchRoutines event, Emitter<RoutineState> emit) async {
    emit(state.copyWith(isLoading: true, errorMessage: null));
    await Future.delayed(const Duration(seconds: 1));
    emit(state.copyWith(isLoading: false, errorMessage: null));
    emit(state.copyWith(searchText: event.query));
  }

  FutureOr<void> _onAddSelectedIcon(
      AddSelectedIcon event, Emitter<RoutineState> emit) {
    emit(state.copyWith(selectedIcon: event.icon));
  }

  // bool _isFirstActionDelay(List<Map<String, dynamic>> actions) {
  //   if (actions.isEmpty) return false;
  //   return actions.first['deviceId'] == 'delay';
  // }

  bool _isLastActionDelay(List<Map<String, dynamic>> actions) {
    if (actions.isEmpty) return false;
    return actions.last['deviceId'] == 'delay';
  }

  Future<void> _onCreateScene(
      CreateSceneEvent event, Emitter<RoutineState> emit) async {
    try {
      // Check if first action is delay
      // if (_isFirstActionDelay(state.thenItems)) {
      //   emit(state.copyWith(
      //     errorMessage: 'Cannot have delay as the first action',
      //     isLoading: false,
      //   ));
      //   return;
      // }

      if (_isLastActionDelay(state.thenItems)) {
        emit(state.copyWith(
          errorMessage:
              'A delay condition cannot be the only or the last action',
          isLoading: false,
        ));
        return;
      }

      emit(state.copyWith(isLoading: true, errorMessage: null));

      final actions = state.thenItems.expand((item) {
        final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
        return functions.map((function) {
          if (function.functionCode == 'automation') {
            return CreateSceneAction(
              actionType: 'automation',
              entityId: function.entityId,
              actionExecutor: function.value,
              executorProperty: null,
            );
          }

          if (item['deviceId'] == 'delay') {
            return CreateSceneAction(
              entityId: function.entityId,
              actionExecutor: 'delay',
              executorProperty: CreateSceneExecutorProperty(
                functionCode: '',
                functionValue: '',
                delaySeconds: int.tryParse(function.value.toString()) ?? 0,
              ),
            );
          }

          return CreateSceneAction(
            actionType: 'scene',
            entityId: function.entityId,
            actionExecutor: 'device_issue',
            executorProperty: CreateSceneExecutorProperty(
              functionCode: function.functionCode,
              functionValue: function.value,
              delaySeconds: 0,
            ),
          );
        });
      }).toList();

      BuildContext context = NavigationService.navigatorKey.currentContext!;
      var createRoutineBloc = context.read<CreateRoutineBloc>();

      final createSceneModel = CreateSceneModel(
        spaceUuid: createRoutineBloc.selectedSpaceId,
        iconId: state.selectedIcon ?? '',
        showInDevice: true,
        sceneName: state.routineName ?? '',
        decisionExpr: 'and',
        actions: actions,
      );

      final result = await SceneApi.createScene(createSceneModel);
      if (result['success']) {
        add(ResetRoutineState());
        add(const LoadScenes());
        add(const LoadAutomation());
      } else {
        emit(state.copyWith(
          isLoading: false,
          errorMessage: 'Something went wrong',
        ));
      }
    } on APIException catch (e) {
      final errorData = e.message;
      String errorMessage = errorData;
      emit(state.copyWith(
        isLoading: false,
        errorMessage: errorMessage,
      ));
    }
  }

  Future<void> _onCreateAutomation(
      CreateAutomationEvent event, Emitter<RoutineState> emit) async {
    try {
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';
      if (state.routineName == null || state.routineName!.isEmpty) {
        emit(state.copyWith(
          errorMessage: 'Automation name is required',
        ));
        CustomSnackBar.redSnackBar('Automation name is required');
        return;
      }
      // if (_isFirstActionDelay(state.thenItems)) {
      //   emit(state.copyWith(
      //     errorMessage: 'Cannot have delay as the first action',
      //     isLoading: false,
      //   ));
      //   CustomSnackBar.redSnackBar('Cannot have delay as the first action');

      //   return;
      // }

      if (_isLastActionDelay(state.thenItems)) {
        emit(state.copyWith(
          errorMessage:
              'A delay condition cannot be the only or the last action',
          isLoading: false,
        ));
        CustomSnackBar.redSnackBar('Cannot have delay as the last action');
        return;
      }
      emit(state.copyWith(isLoading: true, errorMessage: null));
      int i = 0;
      final conditions = state.ifItems.expand((item) {
        final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
        return functions.map((function) {
          return Condition(
            code: i++,
            entityId: function.entityId,
            entityType: 'device_report',
            expr: ConditionExpr(
              statusCode: function.functionCode,
              comparator: function.condition ?? '==',
              statusValue: function.value,
            ),
          );
        });
      }).toList();

      if (conditions.isEmpty) {
        emit(state.copyWith(
          isLoading: false,
          errorMessage: 'At least one condition is required',
        ));
        return;
      }

      final actions = state.thenItems.expand((item) {
        if (item['type'] == 'tap_to_run') {
          return [
            AutomationAction(
              actionType: 'scene',
              entityId: item['deviceId'],
              actionExecutor: 'rule_trigger',
            ),
          ];
        }

        final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];

        return functions.map((function) {
          if (function.functionCode == 'automation') {
            return AutomationAction(
              actionType: 'automation',
              entityId: function.entityId,
              actionExecutor: function.value,
              executorProperty: null,
            );
          }

          if (item['deviceId'] == 'delay') {
            return AutomationAction(
              entityId: function.entityId,
              actionExecutor: 'delay',
              executorProperty: ExecutorProperty(
                delaySeconds: int.tryParse(function.value.toString()) ?? 0,
              ),
            );
          }

          return AutomationAction(
            entityId: function.entityId,
            actionExecutor: 'device_issue',
            executorProperty: ExecutorProperty(
              functionCode: function.functionCode,
              functionValue: function.value,
            ),
          );
        });
      }).toList();
      BuildContext context = NavigationService.navigatorKey.currentContext!;
      var createRoutineBloc = context.read<CreateRoutineBloc>();

      final createAutomationModel = CreateAutomationModel(
        spaceUuid: createRoutineBloc.selectedSpaceId,
        automationName: state.routineName ?? '',
        decisionExpr: state.selectedAutomationOperator,
        effectiveTime: EffectiveTime(
          start: state.effectiveTime?.start ?? '00:00',
          end: state.effectiveTime?.end ?? '23:59',
          loops: state.effectiveTime?.loops ?? '1111111',
        ),
        conditions: conditions,
        actions: actions,
      );

      final result =
          await SceneApi.createAutomation(createAutomationModel, projectUuid);
      if (result['success']) {
        add(ResetRoutineState());
        add(const LoadAutomation());
        add(const LoadScenes());
      } else {
        emit(state.copyWith(
          isLoading: false,
          errorMessage: result['message'],
        ));
        CustomSnackBar.redSnackBar('Something went wrong');
      }
    } on APIException catch (e) {
      final errorData = e.message;
      String errorMessage = errorData;
      emit(state.copyWith(
        isLoading: false,
        errorMessage: errorMessage,
      ));
      CustomSnackBar.redSnackBar(errorMessage);
    }
  }

  FutureOr<void> _onRemoveDragCard(
      RemoveDragCard event, Emitter<RoutineState> emit) {
    if (event.isFromThen) {
      final thenItems = List<Map<String, dynamic>>.from(state.thenItems);
      final selectedFunctions =
          Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);

      thenItems.removeAt(event.index);
      selectedFunctions.remove(event.key);
      emit(state.copyWith(
          thenItems: thenItems, selectedFunctions: selectedFunctions));
    } else {
      final ifItems = List<Map<String, dynamic>>.from(state.ifItems);
      final selectedFunctions =
          Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);

      ifItems.removeAt(event.index);
      selectedFunctions.remove(event.key);
      if (ifItems.isEmpty && state.thenItems.isEmpty) {
        emit(state.copyWith(
            ifItems: ifItems,
            selectedFunctions: selectedFunctions,
            isAutomation: false,
            isTabToRun: false));
      } else {
        emit(state.copyWith(
            ifItems: ifItems, selectedFunctions: selectedFunctions));
      }
    }
  }

  FutureOr<void> _changeOperatorOperator(
      ChangeAutomationOperator event, Emitter<RoutineState> emit) {
    emit(state.copyWith(
      selectedAutomationOperator: event.operator,
    ));
  }

  FutureOr<void> _onEffectiveTimeEvent(
      EffectiveTimePeriodEvent event, Emitter<RoutineState> emit) {
    emit(state.copyWith(effectiveTime: event.effectiveTime));
  }

  FutureOr<void> _onSetRoutineName(
      SetRoutineName event, Emitter<RoutineState> emit) {
    emit(state.copyWith(
      routineName: event.name,
    ));
  }

  // (
  //   List<Map<String, dynamic>>,
  //   List<Map<String, dynamic>>,
  //   Map<String, List<DeviceFunctionData>>
  // ) _createCardData(
  //   List<RoutineAction> actions,
  //   List<RoutineCondition>? conditions,
  //   Map<String, List<DeviceFunctionData>> currentFunctions,
  //   bool isTabToRun,
  // ) {
  //   final ifItems = isTabToRun
  //       ? [
  //           {
  //             'entityId': 'tab_to_run',
  //             'uniqueCustomId': const Uuid().v4(),
  //             'deviceId': 'tab_to_run',
  //             'title': 'Tap to run',
  //             'productType': 'tab_to_run',
  //             'imagePath': Assets.tabToRun,
  //           }
  //         ]
  //       : conditions?.map((condition) {
  //             final matchingDevice = state.devices.firstWhere(
  //               (device) => device.uuid == condition.entityId,
  //               orElse: () => AllDevicesModel(
  //                 uuid: condition.entityId,
  //                 name: condition.entityId,
  //                 productType: condition.entityType,
  //               ),
  //             );

  //             final cardData = {
  //               'entityId': condition.entityId,
  //               'uniqueCustomId': const Uuid().v4(),
  //               'deviceId': condition.entityId,
  //               'title': matchingDevice.name ?? condition.entityId,
  //               'productType': condition.entityType,
  //               'imagePath':
  //                   matchingDevice.getDefaultIcon(condition.entityType),
  //             };

  //             final functions = matchingDevice.functions;

  //             for (var function in functions) {
  //               if (function.code == condition.expr.statusCode) {
  //                 currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
  //                   DeviceFunctionData(
  //                     entityId: condition.entityId,
  //                     functionCode: condition.expr.statusCode,
  //                     value: condition.expr.statusValue,
  //                     operationName: function.operationName,
  //                   ),
  //                 ];
  //                 break;
  //               }
  //             }

  //             return cardData;
  //           }).toList() ??
  //           [];

  //   final thenItems = actions.map((action) {
  //     final matchingDevice = state.devices.firstWhere(
  //       (device) => device.uuid == action.entityId,
  //       orElse: () => AllDevicesModel(
  //         uuid: action.entityId,
  //         name: action.entityId,
  //         productType: action.productType,
  //       ),
  //     );

  //     final cardData = {
  //       'entityId': action.entityId,
  //       'uniqueCustomId': const Uuid().v4(),
  //       'deviceId':
  //           action.actionExecutor == 'delay' ? 'delay' : action.entityId,
  //       'title': action.actionExecutor == 'delay'
  //           ? 'Delay'
  //           : (matchingDevice.name ?? 'Device'),
  //       'productType': action.productType,
  //       'imagePath': matchingDevice.getDefaultIcon(action.productType),
  //     };

  //     final functions = matchingDevice.functions;

  //     if (action.executorProperty != null && action.actionExecutor != 'delay') {
  //       final functionCode = action.executorProperty!.functionCode;
  //       for (var function in functions) {
  //         if (function.code == functionCode) {
  //           currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
  //             DeviceFunctionData(
  //               entityId: action.entityId,
  //               functionCode: functionCode ?? '',
  //               value: action.executorProperty!.functionValue,
  //               operationName: function.operationName,
  //             ),
  //           ];
  //           break;
  //         }
  //       }
  //     } else if (action.actionExecutor == 'delay') {
  //       final delayFunction = DelayFunction(
  //         deviceId: action.entityId,
  //         deviceName: 'Delay',
  //       );
  //       currentFunctions[cardData['uniqueCustomId'] ?? ''] = [
  //         DeviceFunctionData(
  //           entityId: action.entityId,
  //           functionCode: 'delay',
  //           value: action.executorProperty?.delaySeconds ?? 0,
  //           operationName: delayFunction.operationName,
  //         ),
  //       ];
  //     }

  //     return cardData;
  //   }).toList();

  //   return (thenItems, ifItems, currentFunctions);
  // }

  Future<void> _onGetSceneDetails(
      GetSceneDetails event, Emitter<RoutineState> emit) async {
    try {
      emit(state.copyWith(
        isLoading: true,
        isTabToRun: true,
        isUpdate: true,
        sceneId: event.sceneId,
        routineName: null,
        isAutomation: false,
        selectedFunctions: {},
        ifItems: [],
        thenItems: [],
        errorMessage: '',
        loadScenesErrorMessage: null,
        loadAutomationErrorMessage: null,
        searchText: '',
        selectedIcon: null,
        selectedAutomationOperator: 'or',
        effectiveTime: null,
      ));

      final sceneDetails = await SceneApi.getSceneDetails(event.sceneId);

      final List<Map<String, dynamic>> thenItems;
      final List<Map<String, dynamic>> ifItems;
      final Map<String, List<DeviceFunctionData>> updatedFunctions =
          Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);

      final Map<String, Map<String, dynamic>> deviceCards = {};

      for (var action in sceneDetails.actions) {
        AllDevicesModel? matchingDevice;
        for (var device in state.devices) {
          if (device.uuid == action.entityId) {
            matchingDevice = device;
            break;
          }
        }

        final deviceId = action.type == 'automation'
            ? '${action.entityId}_automation'
            : action.actionExecutor == 'delay'
                ? '${action.entityId}_delay'
                : const Uuid().v4();

        // if (!deviceCards.containsKey(deviceId)) {
        deviceCards[deviceId] = {
          'entityId': action.entityId,
          'deviceId':
              action.actionExecutor == 'delay' ? 'delay' : action.entityId,
          'uniqueCustomId':
              action.type == 'automation' || action.actionExecutor == 'delay'
                  ? action.entityId
                  : const Uuid().v4(),
          'title': action.actionExecutor == 'delay'
              ? 'Delay'
              : action.type == 'automation'
                  ? action.name ?? 'Automation'
                  : (matchingDevice?.name ?? 'Device'),
          'productType': action.productType,
          'functions': matchingDevice?.functions,
          'imagePath': action.type == 'automation'
              ? Assets.automation
              : action.actionExecutor == 'delay'
                  ? Assets.delay
                  : matchingDevice?.getDefaultIcon(action.productType),
          'device': matchingDevice,
          'name': action.name,
          'type': action.type,
          'tag': matchingDevice?.deviceTags?.isNotEmpty ?? false
              ? matchingDevice?.deviceTags![0].name ?? ''
              : '',
          'subSpace': matchingDevice?.deviceSubSpace?.subspaceName ?? '',
        };
        // }

        final cardData = deviceCards[deviceId]!;
        final uniqueCustomId = cardData['uniqueCustomId'].toString();

        if (!updatedFunctions.containsKey(uniqueCustomId)) {
          updatedFunctions[uniqueCustomId] = [];
        }

        if (action.type == 'automation') {
          updatedFunctions[uniqueCustomId]!.add(
            DeviceFunctionData(
              entityId: action.entityId,
              functionCode: 'automation',
              value: action.actionExecutor,
              operationName: 'Automation',
            ),
          );
          // emit(state.copyWith(automationActionExecutor: action.actionExecutor));
        } else if (action.executorProperty != null &&
            action.actionExecutor != 'delay') {
          final functions = matchingDevice?.functions ?? [];
          final functionCode = action.executorProperty?.functionCode;
          for (DeviceFunction function in functions) {
            if (function.code == functionCode) {
              updatedFunctions[uniqueCustomId]!.add(
                DeviceFunctionData(
                  entityId: action.entityId,
                  functionCode: functionCode ?? '',
                  value: action.executorProperty?.functionValue,
                  operationName: function.operationName,
                ),
              );
              break;
            }
          }
        } else if (action.actionExecutor == 'delay') {
          final delayFunction = DelayFunction(
            deviceId: action.entityId,
            deviceName: 'Delay',
          );
          updatedFunctions[uniqueCustomId]!.add(
            DeviceFunctionData(
              entityId: action.entityId,
              functionCode: 'delay',
              value: action.executorProperty?.delaySeconds ?? 0,
              operationName: delayFunction.operationName,
            ),
          );
        }
      }

      thenItems = deviceCards.values.toList();

      ifItems = [
        {
          'entityId': 'tab_to_run',
          'uniqueCustomId': const Uuid().v4(),
          'deviceId': 'tab_to_run',
          'title': 'Tap to run',
          'productType': 'tab_to_run',
          'imagePath': Assets.tabToRun,
        }
      ];

      emit(state.copyWith(
        isLoading: false,
        routineName: sceneDetails.name,
        selectedIcon: sceneDetails.iconId,
        selectedAutomationOperator: sceneDetails.decisionExpr,
        effectiveTime: sceneDetails.effectiveTime,
        isAutomation: false,
        isTabToRun: event.isTabToRun,
        thenItems: thenItems,
        ifItems: ifItems,
        selectedFunctions: updatedFunctions,
        sceneId: sceneDetails.sceneId,
      ));
    } catch (e) {
      emit(state.copyWith(
        isLoading: false,
        errorMessage: 'Failed to load scene details: $e',
      ));
    }
  }

  FutureOr<void> _onResetRoutineState(
      ResetRoutineState event, Emitter<RoutineState> emit) {
    emit(state.copyWith(
        ifItems: [],
        thenItems: [],
        selectedFunctions: {},
        scenes: [],
        sceneId: '',
        automationId: '',
        automations: [],
        isLoading: false,
        errorMessage: '',
        loadScenesErrorMessage: null,
        loadAutomationErrorMessage: null,
        searchText: '',
        selectedIcon: '',
        isTabToRun: false,
        isAutomation: false,
        selectedAutomationOperator: 'or',
        effectiveTime: null,
        routineName: '',
        isUpdate: false,
        createRoutineView: false));
  }

  FutureOr<void> _deleteScene(
      DeleteScene event, Emitter<RoutineState> emit) async {
    try {
      final projectId = await ProjectManager.getProjectUUID() ?? '';

      emit(state.copyWith(isLoading: true));
      BuildContext context = NavigationService.navigatorKey.currentContext!;
      var spaceBloc = context.read<SpaceTreeBloc>();
      if (state.isTabToRun) {
        await SceneApi.deleteScene(
            unitUuid: spaceBloc.state.selectedSpaces[0],
            sceneId: state.sceneId ?? '');
      } else {
        await SceneApi.deleteAutomation(
            unitUuid: spaceBloc.state.selectedSpaces[0],
            automationId: state.automationId ?? '',
            projectId: projectId);
      }
      // var createRoutineBloc = context.read<CreateRoutineBloc>();
      // if (state.isTabToRun) {
      //   await SceneApi.deleteScene(
      //       unitUuid: createRoutineBloc.selectedSpaceId,
      //       sceneId: state.sceneId ?? '');
      // } else {
      //   await SceneApi.deleteAutomation(
      //       projectId: projectId,
      //       unitUuid: createRoutineBloc.selectedSpaceId,
      //       automationId: state.automationId ?? '');
      // }

      add(const LoadScenes());
      add(const LoadAutomation());
      add(ResetRoutineState());
      emit(state.copyWith(isLoading: false, createRoutineView: false));
    } on APIException catch (e) {
      final errorData = e.message;
      String errorMessage = errorData;
      emit(state.copyWith(
        isLoading: false,
        errorMessage: errorMessage,
      ));
      CustomSnackBar.redSnackBar(errorMessage);
    }
  }

  // FutureOr<void> _deleteAutomation(DeleteAutomation event, Emitter<RoutineState> emit) {
  //   try {
  //     emit(state.copyWith(isLoading: true));
  //     add(const LoadAutomation(spaceId));
  //     add(const LoadScenes(spaceId, communityId));
  //     emit(_resetState());
  //   } catch (e) {
  //     emit(state.copyWith(
  //       isLoading: false,
  //       errorMessage: 'Failed to delete automation',
  //     ));
  //   }
  // }

  FutureOr<void> _fetchDevices(
      FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
    emit(state.copyWith(isLoading: true));
    try {
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';
      List<AllDevicesModel> devices = [];
      BuildContext context = NavigationService.navigatorKey.currentContext!;
      var createRoutineBloc = context.read<CreateRoutineBloc>();
      var spaceBloc = context.read<SpaceTreeBloc>();

      if (createRoutineBloc.selectedSpaceId == '' &&
          createRoutineBloc.selectedCommunityId == '') {
        for (var communityId in spaceBloc.state.selectedCommunities) {
          List<String> spacesList =
              spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
          for (var spaceId in spacesList) {
            devices.addAll(await DevicesManagementApi()
                .fetchDevices(communityId, spaceId, projectUuid));
          }
        }
      } else {
        devices.addAll(await DevicesManagementApi().fetchDevices(
            createRoutineBloc.selectedCommunityId,
            createRoutineBloc.selectedSpaceId,
            projectUuid));
      }

      emit(state.copyWith(isLoading: false, devices: devices));
    } catch (e) {
      emit(state.copyWith(isLoading: false));
    }
  }

  FutureOr<void> _onUpdateScene(
      UpdateScene event, Emitter<RoutineState> emit) async {
    try {
      // Check if first action is delay
      // if (_isFirstActionDelay(state.thenItems)) {
      //   emit(state.copyWith(
      //     errorMessage: 'Cannot have delay as the first action',
      //     isLoading: false,
      //   ));

      //   return;
      // }

      if (_isLastActionDelay(state.thenItems)) {
        emit(state.copyWith(
          errorMessage:
              'A delay condition cannot be the only or the last action',
          isLoading: false,
        ));
        return;
      }

      emit(state.copyWith(isLoading: true, errorMessage: null));

      final actions = state.thenItems.expand((item) {
        final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
        return functions.map((function) {
          if (function.functionCode == 'automation') {
            return CreateSceneAction(
              actionType: 'automation',
              entityId: function.entityId,
              actionExecutor: function.value,
              executorProperty: null,
            );
          }

          if (item['deviceId'] == 'delay') {
            return CreateSceneAction(
              entityId: function.entityId,
              actionExecutor: 'delay',
              executorProperty: CreateSceneExecutorProperty(
                functionCode: '',
                functionValue: '',
                delaySeconds: int.tryParse(function.value.toString()) ?? 0,
              ),
            );
          }

          return CreateSceneAction(
            entityId: function.entityId,
            actionExecutor: 'device_issue',
            executorProperty: CreateSceneExecutorProperty(
              functionCode: function.functionCode,
              functionValue: function.value,
              delaySeconds: 0,
            ),
          );
        });
      }).toList();

      final createSceneModel = CreateSceneModel(
        spaceUuid: state.sceneId ?? '',
        iconId: state.selectedIcon ?? '',
        showInDevice: true,
        sceneName: state.routineName ?? '',
        decisionExpr: 'and',
        actions: actions,
      );

      final result =
          await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
      if (result['success']) {
        add(ResetRoutineState());
        add(const LoadScenes());
        add(const LoadAutomation());
      } else {
        emit(state.copyWith(
          isLoading: false,
          errorMessage: result['message'],
        ));
      }
    } catch (e) {
      emit(state.copyWith(
        isLoading: false,
        errorMessage: 'Something went wrong',
      ));
    }
  }

  FutureOr<void> _onUpdateAutomation(
      UpdateAutomation event, Emitter<RoutineState> emit) async {
    try {
      if (state.routineName == null || state.routineName!.isEmpty) {
        emit(state.copyWith(
          errorMessage: 'Automation name is required',
        ));
        return;
      }
      // if (_isFirstActionDelay(state.thenItems)) {
      //   emit(state.copyWith(
      //     errorMessage: 'Cannot have delay as the first action',
      //     isLoading: false,
      //   ));
      //   return;
      // }

      if (_isLastActionDelay(state.thenItems)) {
        emit(state.copyWith(
          errorMessage: 'Cannot have delay as the last action',
          isLoading: false,
        ));
        return;
      }
      emit(state.copyWith(isLoading: true, errorMessage: null));
      int i = 0;
      final conditions = state.ifItems.expand((item) {
        final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];
        return functions.map((function) {
          return Condition(
            code: i++,
            entityId: function.entityId,
            entityType: 'device_report',
            expr: ConditionExpr(
              statusCode: function.functionCode,
              comparator: function.condition ?? '==',
              statusValue: function.value,
            ),
          );
        });
      }).toList();

      if (conditions.isEmpty) {
        emit(state.copyWith(
          isLoading: false,
          errorMessage: 'At least one condition is required',
        ));
        return;
      }

      final actions = state.thenItems.expand((item) {
        if (item['type'] == 'tap_to_run' || item['type'] == 'scene') {
          return [
            AutomationAction(
              actionType: 'scene',
              entityId: item['deviceId'],
              actionExecutor: 'rule_trigger',
            ),
          ];
        }

        final functions = state.selectedFunctions[item['uniqueCustomId']] ?? [];

        return functions.map((function) {
          if (function.functionCode == 'automation') {
            return AutomationAction(
              actionType: 'automation',
              entityId: function.entityId,
              actionExecutor: function.value,
              executorProperty: null,
            );
          }

          if (item['deviceId'] == 'delay') {
            return AutomationAction(
              entityId: function.entityId,
              actionType: 'automation',
              actionExecutor: 'delay',
              executorProperty: ExecutorProperty(
                delaySeconds: int.tryParse(function.value.toString()) ?? 0,
              ),
            );
          }

          return AutomationAction(
            entityId: function.entityId,
            actionExecutor: 'device_issue',
            actionType: 'automation',
            executorProperty: ExecutorProperty(
              functionCode: function.functionCode,
              functionValue: function.value,
            ),
          );
        });
      }).toList();

      BuildContext context = NavigationService.navigatorKey.currentContext!;
      var spaceBloc = context.read<CreateRoutineBloc>();

      final createAutomationModel = CreateAutomationModel(
        spaceUuid: spaceBloc.selectedSpaceId,
        automationName: state.routineName ?? '',
        decisionExpr: state.selectedAutomationOperator,
        effectiveTime: EffectiveTime(
          start: state.effectiveTime?.start ?? '00:00',
          end: state.effectiveTime?.end ?? '23:59',
          loops: state.effectiveTime?.loops ?? '1111111',
        ),
        conditions: conditions,
        actions: actions,
      );
      final projectId = await ProjectManager.getProjectUUID() ?? '';
      final result = await SceneApi.updateAutomation(
          createAutomationModel, state.automationId ?? '', projectId);

      if (result['success']) {
        add(ResetRoutineState());
        add(const LoadAutomation());
        add(const LoadScenes());
      } else {
        emit(state.copyWith(
          isLoading: false,
          errorMessage: result['message'],
        ));
      }
    } on APIException catch (e) {
      final errorData = e.message;
      emit(state.copyWith(
        isLoading: false,
        errorMessage: errorData,
      ));
    }
  }

  Future<void> _onGetAutomationDetails(
      GetAutomationDetails event, Emitter<RoutineState> emit) async {
    try {
      final projectUuid = await ProjectManager.getProjectUUID() ?? '';
      emit(state.copyWith(
        isLoading: true,
        isUpdate: true,
        isTabToRun: false,
        automationId: event.automationId,
        isAutomation: true,
        ifItems: [],
        thenItems: [],
      ));

      final automationDetails =
          await SceneApi.getAutomationDetails(event.automationId, projectUuid);

      final Map<String, Map<String, dynamic>> deviceIfCards = {};
      final Map<String, Map<String, dynamic>> deviceThenCards = {};

      final Map<String, List<DeviceFunctionData>> updatedFunctions =
          Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);

      for (RoutineCondition condition in automationDetails.conditions ?? []) {
        AllDevicesModel? matchingDevice = state.devices.firstWhere(
          (device) => device.uuid == condition.entityId,
          orElse: () => AllDevicesModel(
            uuid: condition.entityId,
            name: condition.entityId,
            productType: condition.productType,
          ),
        );

        final deviceId = const Uuid().v4();

        // if (!deviceIfCards.containsKey(deviceId)) {
        deviceIfCards[deviceId] = {
          'entityId': condition.entityId,
          'deviceId': condition.entityId,
          'uniqueCustomId': const Uuid().v4(),
          'title': matchingDevice.name ?? 'Device',
          'productType': condition.productType,
          'functions': matchingDevice.functions,
          'imagePath': matchingDevice.getDefaultIcon(condition.productType),
          'device': matchingDevice,
          'type': 'condition',
          'tag': matchingDevice.deviceTags?.isNotEmpty ?? false
              ? matchingDevice.deviceTags![0].name
              : '',
          'subSpace': matchingDevice.deviceSubSpace?.subspaceName ?? '',
        };
        // }

        final cardData = deviceIfCards[deviceId]!;
        final uniqueCustomId = cardData['uniqueCustomId'].toString();

        if (!updatedFunctions.containsKey(uniqueCustomId)) {
          updatedFunctions[uniqueCustomId] = [];
        }

        final functions = matchingDevice.functions;
        for (var function in functions) {
          if (function.code == condition.expr.statusCode) {
            updatedFunctions[uniqueCustomId]!.add(
              DeviceFunctionData(
                entityId: condition.entityId,
                functionCode: condition.expr.statusCode,
                value: condition.expr.statusValue,
                operationName: function.operationName,
              ),
            );
            break;
          }
        }
      }

      // Process actions (thenItems)
      for (var action in automationDetails.actions) {
        AllDevicesModel? matchingDevice = state.devices.firstWhere(
          (device) => device.uuid == action.entityId,
          orElse: () => AllDevicesModel(
            uuid: action.entityId,
            name: action.entityId,
            productType: action.productType,
          ),
        );

        final deviceId = const Uuid().v4();

        // if (!deviceThenCards.containsKey(deviceId)) {
        deviceThenCards[deviceId] = {
          'entityId': action.entityId,
          'deviceId':
              action.actionExecutor == 'delay' ? 'delay' : action.entityId,
          'uniqueCustomId': const Uuid().v4(),
          'title': action.actionExecutor == 'delay'
              ? 'Delay'
              : (action.type == 'scene' || action.type == 'automation')
                  ? action.name
                  : (matchingDevice.name ?? 'Device'),
          'productType': action.productType,
          'functions': matchingDevice.functions,
          'imagePath': action.actionExecutor == 'delay'
              ? Assets.delay
              : action.type == 'automation'
                  ? Assets.automation
                  : matchingDevice.getDefaultIcon(action.productType),
          'device': matchingDevice,
          'type': action.type == 'scene'
              ? 'scene'
              : action.type == 'automation'
                  ? 'automation'
                  : 'action',
          'icon': action.icon ?? '',
          'tag': matchingDevice.deviceTags?.isNotEmpty ?? false
              ? matchingDevice.deviceTags![0].name
              : '',
          'subSpace': matchingDevice.deviceSubSpace?.subspaceName ?? '',
        };
        // }

        final cardData = deviceThenCards[deviceId]!;
        final uniqueCustomId = cardData['uniqueCustomId'].toString();

        if (!updatedFunctions.containsKey(uniqueCustomId)) {
          updatedFunctions[uniqueCustomId] = [];
        }

        if (action.executorProperty != null &&
            action.actionExecutor != 'delay') {
          final functions = matchingDevice.functions;
          final functionCode = action.executorProperty!.functionCode;
          for (var function in functions) {
            if (function.code == functionCode) {
              updatedFunctions[uniqueCustomId]!.add(
                DeviceFunctionData(
                  entityId: action.entityId,
                  functionCode: functionCode ?? '',
                  value: action.executorProperty!.functionValue,
                  operationName: function.operationName,
                ),
              );
              break;
            }
          }
        } else if (action.actionExecutor == 'delay') {
          final delayFunction = DelayFunction(
            deviceId: action.entityId,
            deviceName: 'Delay',
          );
          updatedFunctions[uniqueCustomId]!.add(
            DeviceFunctionData(
              entityId: action.entityId,
              functionCode: 'delay',
              value: action.executorProperty?.delaySeconds ?? 0,
              operationName: delayFunction.operationName,
            ),
          );
        } else if (action.actionExecutor == 'rule_disable' ||
            action.actionExecutor == 'rule_enable') {
          updatedFunctions[uniqueCustomId]!.add(
            DeviceFunctionData(
              entityId: action.entityId,
              functionCode: 'automation',
              value: action.actionExecutor,
              operationName: action.name ?? 'Automation',
            ),
          );
        }
      }

      final ifItems = deviceIfCards.values
          .where((card) => card['type'] == 'condition')
          .toList();
      final thenItems = deviceThenCards.values
          .where((card) =>
              card['type'] == 'action' ||
              card['type'] == 'automation' ||
              card['type'] == 'scene')
          .toList();

      emit(state.copyWith(
        isLoading: false,
        routineName: automationDetails.name,
        selectedAutomationOperator: automationDetails.decisionExpr,
        effectiveTime: automationDetails.effectiveTime,
        isAutomation: true,
        thenItems: thenItems,
        ifItems: ifItems,
        selectedFunctions: updatedFunctions,
        automationId: automationDetails.automationId,
      ));
    } catch (e) {
      emit(state.copyWith(
        isLoading: false,
        errorMessage: 'Failed to load automation details: $e',
      ));
    }
  }

  Future<void> _onSceneTrigger(
      SceneTrigger event, Emitter<RoutineState> emit) async {
    emit(state.copyWith(loadingSceneId: event.sceneId));

    try {
      final success = await SceneApi.triggerScene(event.sceneId!);

      if (success) {
        emit(state.copyWith(
          loadingSceneId: null,
          // Add success state if needed
        ));
        // Optional: Add delay to show success feedback
        await Future.delayed(const Duration(milliseconds: 500));
      } else {
        emit(state.copyWith(
          loadingSceneId: null,
          errorMessage: 'Trigger failed',
        ));
      }
    } catch (e) {
      emit(state.copyWith(
        loadingSceneId: null,
        errorMessage: 'Trigger error: ${e.toString()}',
      ));
    }
  }

  Future<void> _onUpdateAutomationStatus(
      UpdateAutomationStatus event, Emitter<RoutineState> emit) async {
    // Create a new set safely
    final currentLoadingIds = state.loadingAutomationIds;
    final newLoadingIds = {...currentLoadingIds!}..add(event.automationId);

    emit(state.copyWith(loadingAutomationIds: newLoadingIds));

    try {
      final projectId = await ProjectManager.getProjectUUID() ?? '';
      final success = await SceneApi.updateAutomationStatus(
          event.automationId, event.automationStatusUpdate, projectId);

      if (success) {
        // await SceneApi.getAutomationByUnitId(
        //     event.automationStatusUpdate.spaceUuid,
        //     event.communityId,
        //     projectId);

        // Remove from loading set safely

        final updatedLoadingIds = {...state.loadingAutomationIds!}
          ..remove(event.automationId);
        final updatedAutomations = changeItemStateOnToggelingSceen(
            state.automations, event.automationId);
        emit(state.copyWith(
          automations: updatedAutomations,
          loadingAutomationIds: updatedLoadingIds,
        ));
      } else {
        final updatedLoadingIds = {...state.loadingAutomationIds!}
          ..remove(event.automationId);
        emit(state.copyWith(
          loadingAutomationIds: updatedLoadingIds,
          errorMessage: 'Update failed',
        ));
      }
    } catch (e) {
      final updatedLoadingIds = {...state.loadingAutomationIds!}
        ..remove(event.automationId);
      emit(state.copyWith(
        loadingAutomationIds: updatedLoadingIds,
        errorMessage: 'Update error: ${e.toString()}',
      ));
    }
  }

  List<ScenesModel> changeItemStateOnToggelingSceen(
      List<ScenesModel> oldSceen, String automationId) {
    return oldSceen.map((scene) {
      if (scene.id == automationId) {
        return ScenesModel(
          id: scene.id,
          sceneTuyaId: scene.sceneTuyaId,
          name: scene.name,
          status: scene.status == 'enable' ? 'disable' : 'enable',
          type: scene.type,
          spaceName: scene.spaceName,
          spaceId: scene.spaceId,
          communityId: scene.communityId,
          icon: scene.icon,
        );
      }
      return scene;
    }).toList();
  }
}
