import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/door_sensor_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart';

class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
  final String DSId;
  DoorSensorBloc({
    required this.DSId,
  }) : super(const DoorSensorState()) {
    on<DoorSensorInitial>(_fetchStatus);
    on<ReportLogsInitial>(fetchLogsForLastMonth);
    on<ToggleLowBatteryEvent>(_toggleLowBattery);
    on<ToggleClosingReminderEvent>(_toggleClosingReminder);
    on<ToggleDoorAlarmEvent>(_toggleDoorAlarm);
  }
  bool lowBattery = false;
  bool closingReminder = false;
  bool doorAlarm = false;
  DoorSensorModel deviceStatus =
      DoorSensorModel(doorContactState: false, batteryPercentage: 0);

  void _fetchStatus(
      DoorSensorInitial event, Emitter<DoorSensorState> emit) async {
    emit(DoorSensorLoadingState());
    try {
      var response = await DevicesAPI.getDeviceStatus(DSId);
      List<StatusModel> statusModelList = [];
      for (var status in response['status']) {
        statusModelList.add(StatusModel.fromJson(status));
      }
      deviceStatus = DoorSensorModel.fromJson(
        statusModelList,
      );
      emit(UpdateState(doorSensor: deviceStatus));
      Future.delayed(const Duration(milliseconds: 500));
      _listenToChanges();
    } catch (e) {
      emit(DoorSensorFailedState(errorMessage: e.toString()));
      return;
    }
  }

  // Toggle functions for each switch
  void _toggleLowBattery(
      ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async {
    emit(LoadingNewSate(doorSensor: deviceStatus));
    try {
      lowBattery = event.isLowBatteryEnabled;
      emit(UpdateState(doorSensor: deviceStatus));

      // API call to update the state, if necessary
      await DevicesAPI.controlDevice(
        DeviceControlModel(
          deviceId: DSId,
          code: 'low_battery',
          value: lowBattery,
        ),
        DSId,
      );
    } catch (e) {
      emit(DoorSensorFailedState(errorMessage: e.toString()));
    }
  }

  void _toggleClosingReminder(
      ToggleClosingReminderEvent event, Emitter<DoorSensorState> emit) async {
    emit(LoadingNewSate(doorSensor: deviceStatus));
    try {
      closingReminder = event.isClosingReminderEnabled;
      emit(UpdateState(doorSensor: deviceStatus));

      // API call to update the state, if necessary
      await DevicesAPI.controlDevice(
        DeviceControlModel(
          deviceId: DSId,
          code: 'closing_reminder',
          value: closingReminder,
        ),
        DSId,
      );
    } catch (e) {
      emit(DoorSensorFailedState(errorMessage: e.toString()));
    }
  }

  void _toggleDoorAlarm(
      ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async {
    emit(LoadingNewSate(doorSensor: deviceStatus));
    try {
      doorAlarm = event.isDoorAlarmEnabled;
      emit(UpdateState(doorSensor: deviceStatus));

      await DevicesAPI.controlDevice(
        DeviceControlModel(
          deviceId: DSId,
          code: 'door_alarm',
          value: doorAlarm,
        ),
        DSId,
      );
    } catch (e) {
      emit(DoorSensorFailedState(errorMessage: e.toString()));
    }
  }

  DeviceReport recordGroups =
      DeviceReport(startTime: '0', endTime: '0', data: []);

  Future<void> fetchLogsForLastMonth(
      ReportLogsInitial event, Emitter<DoorSensorState> emit) async {
    DateTime now = DateTime.now();

    DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);

    int startTime = lastMonth.millisecondsSinceEpoch;
    int endTime = now.millisecondsSinceEpoch;
    try {
      emit(DoorSensorLoadingState());
      var response = await DevicesAPI.getReportLogs(
        startTime: startTime.toString(),
        endTime: endTime.toString(),
        deviceUuid: DSId,
        code: 'doorcontact_state',
      );
      recordGroups = response;
      emit(UpdateState(doorSensor: deviceStatus));
    } on DioException catch (e) {
      final errorData = e.response!.data;
      String errorMessage = errorData['message'];
    }
  }

  // real-time database
  Timer? _timer;
  StreamSubscription<DatabaseEvent>? _streamSubscription;
  void _listenToChanges() {
    try {
      _streamSubscription?.cancel();
      DatabaseReference ref =
          FirebaseDatabase.instance.ref('device-status/$DSId');
      Stream<DatabaseEvent> stream = ref.onValue;

      _streamSubscription = stream.listen((DatabaseEvent event) async {
        if (_timer != null) {
          await Future.delayed(const Duration(seconds: 2));
        }
        Map<dynamic, dynamic> usersMap =
            event.snapshot.value as Map<dynamic, dynamic>;
        List<StatusModel> statusList = [];
        usersMap['status'].forEach((element) {
          statusList
              .add(StatusModel(code: element['code'], value: element['value']));
        });
        deviceStatus = DoorSensorModel.fromJson(statusList);
        if (!isClosed) {
          add(
            DoorSensorSwitch(switchD: deviceStatus.doorContactState),
          );
        }
      });
    } catch (_) {}
  }

  @override
  Future<void> close() async {
    _streamSubscription?.cancel();
    _streamSubscription = null;
    return super.close();
  }
}
