import 'dart:developer';

import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart';

abstract interface class BatchControlDevicesService {
  Future<bool> batchControlDevices({
    required List<String> uuids,
    required String code,
    required Object value,
  });
}

final class RemoteBatchControlDevicesService
    implements BatchControlDevicesService {
  @override
  Future<bool> batchControlDevices({
    required List<String> uuids,
    required String code,
    required Object value,
  }) async {
    try {
      final body = {
        'devicesUuid': uuids,
        'code': code,
        'value': value,
        'operationType': 'COMMAND',
      };

      final response = await HTTPService().post(
        path: ApiEndpoints.deviceBatchControl,
        body: body,
        showServerMessage: true,
        expectedResponseModel: (json) => (json['success'] as bool?) ?? false,
      );

      return response;
    } catch (e) {
      log('Error fetching $e', name: 'BatchControlDevicesService');
      return false;
    }
  }
}

final class DebouncedBatchControlDevicesService
    implements BatchControlDevicesService {
  final BatchControlDevicesService decoratee;
  final Duration debounceDuration;

  DebouncedBatchControlDevicesService({
    required this.decoratee,
    this.debounceDuration = const Duration(milliseconds: 1500),
  });

  final _pendingRequests = <(List<String> uuids, String code, Object value)>[];
  var _isProcessing = false;

  @override
  Future<bool> batchControlDevices({
    required List<String> uuids,
    required String code,
    required Object value,
  }) async {
    _pendingRequests.add((uuids, code, value));

    if (_isProcessing) return false;

    _isProcessing = true;

    await Future.delayed(debounceDuration);

    final groupedRequests =
        <String, (List<String> uuids, String code, Object value)>{};
    for (final request in _pendingRequests) {
      final (_, requestCode, requestValue) = request;
      groupedRequests[requestCode] = request;
    }
    _pendingRequests.clear();

    try {
      var allSuccessful = true;
      for (final request in groupedRequests.values) {
        final (lastRequestUuids, lastRequestCode, lastRequestValue) = request;
        final success = await decoratee.batchControlDevices(
          uuids: lastRequestUuids,
          code: lastRequestCode,
          value: lastRequestValue,
        );
        if (!success) allSuccessful = false;
      }
      return allSuccessful;
    } finally {
      _isProcessing = false;
    }
  }
}
