import 'dart:async';
import 'dart:convert';

import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
import 'package:syncrow_app/features/devices/model/function_model.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';

import '../../features/devices/model/create_temporary_password_model.dart';

class DevicesAPI {
  static final HTTPService _httpService = HTTPService();

  static Future<Map<String, dynamic>> firmwareDevice(
      {required String deviceId, required String firmwareVersion}) async {
    try {
      final response = await _httpService.post(
        path: ApiEndpoints.firmwareDevice
            .replaceAll('{deviceUuid}', deviceId)
            .replaceAll('{firmwareVersion}', firmwareVersion),
        showServerMessage: false,
        expectedResponseModel: (json) {
          return json;
        },
      );
      return response;
    } catch (e) {
      rethrow;
    }
  }

  static Future<Map<String, dynamic>> putDeviceName(
      {required String deviceId, required String deviceName}) async {
    try {
      final response = await _httpService.put(
        path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId),
        body: {"deviceName": deviceName},
        expectedResponseModel: (json) {
          return json['data'];
        },
      );
      return response;
    } catch (e) {
      rethrow;
    }
  }

  static Future<Map<String, dynamic>> controlDevice(
      DeviceControlModel controlModel, String deviceId) async {
    try {
      final response = await _httpService.post(
        path: ApiEndpoints.controlDevice.replaceAll('{deviceUuid}', deviceId),
        body: controlModel.toJson(),
        showServerMessage: true,
        expectedResponseModel: (json) {
          return json;
        },
      );
      return response;
    } catch (e) {
      rethrow;
    }
  }

  static Future<bool> openDoorLock(String deviceId) async {
    final response = await _httpService.post(
      path: ApiEndpoints.openDoorLock.replaceAll('{doorLockUuid}', deviceId),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json['success'] ?? false;
      },
    );
    return response;
  }

  static Future<List<DevicesCategoryModel>> fetchGroups(String spaceId) async {
    final response = await _httpService.get(
      path: ApiEndpoints.groupBySpace.replaceAll('{unitUuid}', spaceId),
      showServerMessage: false,
      expectedResponseModel: (json) => DevicesCategoryModel.fromJsonList(json),
    );

    return response;
  }

  static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
    final response = await _httpService.get(
      path: ApiEndpoints.deviceFunctionsStatus
          .replaceAll('{deviceUuid}', deviceId),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json['data'];
      },
    );
    return response;
  }

  static Future<Map<String, dynamic>> getPowerClampStatus(
      String deviceId) async {
    final response = await _httpService.get(
      path: ApiEndpoints.deviceFunctionsStatus
          .replaceAll('{deviceUuid}', deviceId),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future<Map<String, dynamic>> renamePass(
      {required String name,
      required String doorLockUuid,
      required String passwordId}) async {
    final response = await _httpService.put(
      path: ApiEndpoints.renamePassword
          .replaceAll('{doorLockUuid}', doorLockUuid)
          .replaceAll('{passwordId}', passwordId),
      body: {"name": name},
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  /// Get Device Functions
  static Future<FunctionModel> deviceFunctions(String deviceId) async {
    final response = await _httpService.get(
        path: ApiEndpoints.deviceFunctions.replaceAll('{deviceUuid}', deviceId),
        showServerMessage: false,
        expectedResponseModel: (json) {
          final functions = FunctionModel.fromJson(json['data']);
          return functions;
        });
    return response;
  }

  static Future getDeviceSceneInfo(String deviceId) async {
    final response = await _httpService.get(
        path: ApiEndpoints.deviceScene.replaceAll('{deviceUuid}', deviceId),
        showServerMessage: false,
        expectedResponseModel: (json) {
          return json['data'];
        });
    return response;
  }

  static Future getSceneBySwitchName(
      {String? deviceId, String? switchName}) async {
    final response = await _httpService.get(
        path: ApiEndpoints.fourSceneByName
            .replaceAll('{deviceUuid}', deviceId!)
            .replaceAll('{switchName}', switchName!),
        showServerMessage: false,
        expectedResponseModel: (json) {
          return json;
        });
    return response;
  }

  static Future postDeviceSceneInfo({
    String? switchName,
    String? sceneUuid,
    String? deviceId,
    String? spaceUuid,
  }) async {
    final response = await _httpService.post(
        path: ApiEndpoints.deviceScene.replaceAll('{deviceUuid}', deviceId!),
        body: jsonEncode(
          {
            "switchName": switchName,
            "sceneUuid": sceneUuid,
            "spaceUuid": spaceUuid
          },
        ),
        showServerMessage: false,
        expectedResponseModel: (json) {
          return json;
        });
    return response;
  }

  static Future getDeviceInfo(String deviceId) async {
    final response = await _httpService.get(
        path: ApiEndpoints.deviceByUuid.replaceAll('{deviceUuid}', deviceId),
        showServerMessage: false,
        expectedResponseModel: (json) {
          return json['data'] as Map<String, dynamic>;
        });
    return response;
  }

  static Future<List<DeviceModel>> getDeviceByGroupName(
      String unitId, String groupName) async {
    final response = await _httpService.get(
      path: ApiEndpoints.devicesByGroupName
          .replaceAll('{unitUuid}', unitId)
          .replaceAll('{groupName}', groupName),
      showServerMessage: false,
      expectedResponseModel: (json) {
        if (json == null || json.isEmpty || json == []) {
          return <DeviceModel>[];
        }
        List<DeviceModel> devices = [];

        for (var device in json) {
          devices.add(DeviceModel.fromJson(device));
        }
        return devices;
      },
    );
    return response;
  }

  static Future<List<DeviceModel>> getDevicesByRoomId({
    required String communityUuid,
    required String spaceUuid,
    required String roomId,
    required String projectId,
  }) async {
    try {
      final String path = ApiEndpoints.deviceByRoom
          .replaceAll('{communityUuid}', communityUuid)
          .replaceAll('{spaceUuid}', spaceUuid)
          .replaceAll('{subSpaceUuid}', roomId)
          .replaceAll('{projectUuid}', projectId);

      final response = await _httpService.get(
        path: path,
        showServerMessage: false,
        expectedResponseModel: (json) {
          final data = json['data'];

          if (data == null || data.isEmpty) {
            return <DeviceModel>[];
          }
          if (json == null || json.isEmpty || json == []) {
            return <DeviceModel>[];
          }
          return data
              .map<DeviceModel>((device) => DeviceModel.fromJson(device))
              .toList();
        },
      );

      return response;
    } catch (e) {
      // Log the error if needed
      // Return an empty list in case of error
      return <DeviceModel>[];
    }
  }

  static Future<List<DeviceModel>> getDevicesByGatewayId(
      String gatewayId) async {
    final response = await _httpService.get(
      path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
      showServerMessage: false,
      expectedResponseModel: (json) {
        List<DeviceModel> devices = [];
        if (json == null || json.isEmpty || json == []) {
          return devices;
        }
        for (var device in json['data']['devices']) {
          devices.add(DeviceModel.fromJson(device));
        }
        return devices;
      },
    );
    return response;
  }

  static Future getTemporaryPasswords(
    String deviceId,
  ) async {
    final response = await _httpService.get(
      path: ApiEndpoints.getTemporaryPassword
          .replaceAll('{doorLockUuid}', deviceId),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future getOneTimePasswords(String deviceId) async {
    final response = await _httpService.get(
      path: ApiEndpoints.getOneTimeTemporaryPassword
          .replaceAll('{doorLockUuid}', deviceId),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future getTimeLimitPasswords(String deviceId) async {
    final response = await _httpService.get(
      path: ApiEndpoints.getMultipleTimeTemporaryPassword
          .replaceAll('{doorLockUuid}', deviceId),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  //create password
  static Future createPassword({
    required String name,
    required String password,
    required String effectiveTime,
    required String invalidTime,
    required String deviceId,
    List<Schedule>? scheduleList,
  }) async {
    Map<String, dynamic> body = {
      "name": name,
      "password": password,
      "effectiveTime": effectiveTime,
      "invalidTime": invalidTime,
    };
    if (scheduleList != null) {
      body["scheduleList"] =
          scheduleList.map((schedule) => schedule.toJson()).toList();
    }
    final response = await _httpService.post(
      path: ApiEndpoints.addTemporaryPassword
          .replaceAll('{doorLockUuid}', deviceId),
      body: body,
      showServerMessage: false,
      expectedResponseModel: (json) => json,
    );
    return response;
  }

  static Future generateOneTimePassword({deviceId}) async {
    try {
      final response = await _httpService.post(
        path: ApiEndpoints.addOneTimeTemporaryPassword
            .replaceAll('{doorLockUuid}', deviceId),
        showServerMessage: false,
        expectedResponseModel: (json) {
          return json;
        },
      );
      return response;
    } catch (e) {
      rethrow;
    }
  }

  static Future generateMultiTimePassword(
      {deviceId, effectiveTime, invalidTime}) async {
    try {
      final response = await _httpService.post(
        path: ApiEndpoints.addMultipleTimeTemporaryPassword
            .replaceAll('{doorLockUuid}', deviceId),
        showServerMessage: true,
        body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime},
        expectedResponseModel: (json) {
          return json;
        },
      );
      return response;
    } catch (e) {
      rethrow;
    }
  }

  static Future<Map<String, dynamic>> deletePassword(
      {required String passwordId, required String deviceId}) async {
    final response = await _httpService.delete(
      path: ApiEndpoints.deleteTemporaryPassword
          .replaceAll('{doorLockUuid}', deviceId)
          .replaceAll('{passwordId}', passwordId),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future<Map<String, dynamic>> postSchedule({
    required String category,
    required String deviceId,
    required String time,
    required String code,
    required bool value,
    required List<String> days,
  }) async {
    final response = await _httpService.post(
      path: ApiEndpoints.saveSchedule.replaceAll('{deviceUuid}', deviceId),
      showServerMessage: false,
      body: jsonEncode(
        {
          "category": category,
          "time": time,
          "function": {
            "code": code,
            "value": value,
          },
          "days": days
        },
      ),
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future getSchedule({
    required String category,
    required String deviceId,
  }) async {
    final response = await _httpService.get(
      path: ApiEndpoints.getSchedule
          .replaceAll('{deviceUuid}', deviceId)
          .replaceAll('{category}', category),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future<bool> changeSchedule({
    required String deviceUuid,
    required String scheduleId,
    required bool enable,
  }) async {
    final response = await _httpService.put(
      path: ApiEndpoints.changeSchedule.replaceAll('{deviceUuid}', deviceUuid),
      body: {"scheduleId": scheduleId, "enable": enable},
      expectedResponseModel: (json) {
        return json['success'];
      },
    );
    return response;
  }

  static Future deleteSchedule({
    required String deviceUuid,
    required String scheduleId,
  }) async {
    final response = await _httpService.delete(
      path: ApiEndpoints.deleteSchedule
          .replaceAll('{deviceUuid}', deviceUuid)
          .replaceAll('{scheduleId}', scheduleId),
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future<DeviceReport> getReportLogs({
    required String deviceUuid,
    required String code,
    required String startTime,
    required String endTime,
  }) async {
    final requestUrl = ApiEndpoints.reportLogs
        .replaceAll('{deviceUuid}', deviceUuid)
        .replaceAll('{code}', code)
        .replaceAll('{startTime}', startTime)
        .replaceAll('{endTime}', endTime);
    final response = await _httpService.get(
      path: requestUrl,
      expectedResponseModel: (json) {
        return DeviceReport.fromJson(json);
      },
    );

    return response;
  }

  static Future deviceBatchController({
    List<String>? devicesUuid,
    String? code,
    var value,
  }) async {
    final response = await _httpService.post(
      path: ApiEndpoints.controlBatch,
      body: {
        "devicesUuid": devicesUuid,
        "code": code,
        "value": value,
        "operationType": 'COMMAND',
      },
      showServerMessage: true,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future deviceBatchStatus({
    List<String>? devicesUuid,
  }) async {
    final response = await _httpService.get(
      path: ApiEndpoints.statusBatch,
      queryParameters: {"devicesUuid": devicesUuid},
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future resetDevise({
    String? devicesUuid,
  }) async {
    final response = await _httpService.post(
      path: ApiEndpoints.resetDevice.replaceAll('{deviceUuid}', devicesUuid!),
      showServerMessage: false,
      body: {
        "devicesUuid": [devicesUuid]
      },
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future unAssignScenesDevice({
    String? deviceUuid,
    String? switchName,
  }) async {
    final response = await _httpService.delete(
      path: ApiEndpoints.unAssignScenesDevice
          .replaceAll('{deviceUuid}', deviceUuid!)
          .replaceAll('{switchName}', switchName!),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return json;
      },
    );
    return response;
  }

  static Future<DeviceReport> getDeviceReports(
    String uuid,
    String code,
  ) async {
    final response = await HTTPService().get(
      path: ApiEndpoints.getDeviceLogs
          .replaceAll('{uuid}', uuid)
          .replaceAll('{code}', code),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return DeviceReport.fromJson(json);
      },
    );
    return response;
  }

  static Future<DeviceReport> getReports(
    String uuid,
    String code,
  ) async {
    final response = await HTTPService().get(
      path: ApiEndpoints.getReportLogs
          .replaceAll('{uuid}', uuid)
          .replaceAll('{code}', code),
      showServerMessage: false,
      expectedResponseModel: (json) {
        return DeviceReport.fromJson(json);
      },
    );
    return response;
  }

  static Future<List<DeviceModel>> getAllDevices({
    required String communityUuid,
    required String spaceUuid,
    required String projectId,
  }) async {
    try {
      final String path = ApiEndpoints.getAllDevices
          .replaceAll('{communityUuid}', communityUuid)
          .replaceAll('{spaceUuid}', spaceUuid)
          .replaceAll('{projectUuid}', projectId);

      final response = await _httpService.get(
        path: path,
        showServerMessage: false,
        expectedResponseModel: (json) {
          final data = json['data'] as List<dynamic>?;

          if (data == null || data.isEmpty) {
            return <DeviceModel>[];
          }
          if (json == null || json.isEmpty || json == []) {
            return <DeviceModel>[];
          }
          final result = <DeviceModel>[];
          for (final device in data) {
            final mappedDevice = DeviceModel.fromJson(device);
            result.add(mappedDevice);
          }
          return result;
        },
      );

      return response;
    } catch (e) {
      // Log the error if needed
      // Return an empty list in case of error
      return <DeviceModel>[];
    }
  }
}
