import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:hub/src/core/data/datasource/hub_remote_datasource.dart';
import 'package:hub/src/core/data/models/get_devices_response_model.dart';
import 'package:hub/src/core/data/models/latest_positions_response_model.dart';
import 'package:hub/src/features/hub/domain/entities/position_entity.dart';
import 'package:legacy_shared/legacy_shared.dart';
import 'package:sf_infrastructure/sf_infrastructure.dart';

class HomeRemoteDatasourceImpl implements HomeRemoteDatasource {
  HomeRemoteDatasourceImpl(this._repository);

  final QuestiaRepository _repository;

  @override
  Future<List<DeviceEntity>> getDevices({required String userId}) async {
    try {
      /*final response = await _repository.get<Map<String, dynamic>>(
        '/$userId/devices',
      );
      final data = response.data!['items'];
      if (data == null || data.isEmpty) {
        throw Exception('Empty response from /:userId/devices');
      }

      final model = GetDevicesResponseModel.fromJson(data);*/
      final model = GetDevicesResponseModel(items: [
        GetDevicesItemResponseModel(
          id: '1',
          identificator: '1111',
          carrierName: 'Carlos',
          carrierGenre: null,
          carrierBirthday: null,
          carrierWeight: 25,
          carrierStepLength: 35,
          phone: '111111111',
          settings: GetDevicesSettingsResponseModel(
            frequency: 0,
            frequencyHeartRate: 0,
            timezone: 1,
            pedometer: true,
            language: 'es',
            alerts: []
          ),
          protocol: '',
          type: '',
          connectionServer: '',
          createdAt: 0,
          flags: GetDevicesFlagsResponseModel(
            isInOrOut: 'in',
            geofenceId: '',
            isBatteryLow: false,
            isDisconnect: false,
          ),
        ),
        GetDevicesItemResponseModel(
          id: '2',
          identificator: '1112',
          carrierName: 'Ana',
          carrierGenre: null,
          carrierBirthday: null,
          carrierWeight: 26,
          carrierStepLength: 36,
          phone: '222222222',
          settings: GetDevicesSettingsResponseModel(
            frequency: 0,
            frequencyHeartRate: 0,
            timezone: 1,
            pedometer: true,
            language: 'es',
            alerts: []
          ),
          protocol: '',
          type: '',
          connectionServer: '',
          createdAt: 0,
          flags: GetDevicesFlagsResponseModel(
            isInOrOut: 'in',
            geofenceId: '',
            isBatteryLow: false,
            isDisconnect: false
          )
        ),
      ]);
      return model.toEntity();
    } on DioException catch (error) {
      throw _mapDioError(
        error,
        defaultMessage: error.message ?? 'Error getting devices',
      );
    }
  }

  @override
  Future<List<PositionEntity>> getLatestPositions({required String deviceId}) async {
    try {
      final response = await _repository.get<Map<String, dynamic>>(
        '/positions/api/identificator/$deviceId/positions',
      );
      final data = response.data?['items'] ?? [];
      if (data == null || data.isEmpty) {
        throw Exception('Empty response from /identificator/:deviceId/positions');
      }

      final model = LatestPositionsResponseModel.fromJson(data);
      /*final model = LatestPositionsResponseModel(items: [
        LatestPositionsItemResponseModel(
            latitude: 43.327116830678186,
            longitude: -3.083269100434551,
            address: LatestPositionsAddressResponseModel(
              street: 'street',
              city: 'city',
              province: 'province',
              state: 'state',
              country: 'country',
            ),
            positionDate: DateTime.now().millisecondsSinceEpoch,
            frequentPlace: false,
            frequentPlaceName: '',
            id: '1',
            deviceIdentificator: deviceId,
            hpe: 0,
            ncell: 65,
            type: 0,
            createdAt: DateTime.now().millisecondsSinceEpoch,
            positionDateOriginal: null,
            message: '',
            networks: [LatestPositionsNetworkResponseModel(SSID: 'SSID', BSSID: 'BSSID', signal: 'signal')],
            ignore: false,
            suspect: false
        ),
        LatestPositionsItemResponseModel(
            latitude: 43.32729043118528,
            longitude: -3.08320596406992,
            address: LatestPositionsAddressResponseModel(
              street: 'street',
              city: 'city',
              province: 'province',
              state: 'state',
              country: 'country',
            ),
            positionDate: DateTime.now().millisecondsSinceEpoch,
            frequentPlace: true,
            frequentPlaceName: 'La cafetería',
            id: '2',
            deviceIdentificator: deviceId,
            hpe: 0,
            ncell: 65,
            type: 0,
            createdAt: DateTime.now().millisecondsSinceEpoch,
            positionDateOriginal: null,
            message: '',
            networks: [],
            ignore: false,
            suspect: false
        ),
      ]);*/
      return model.toEntity();
    } on DioException catch (error) {
      throw _mapDioError(
        error,
        defaultMessage: error.message ?? 'Error getting latest position',
      );
    }
  }
}

Exception _mapDioError(DioException error, {required String defaultMessage}) {
  final apiMsg = _extractApiMessage(error.response?.data);
  final msg = apiMsg ?? error.message ?? defaultMessage;
  return Exception(msg);
}

String? _extractApiMessage(Object? data) {
  if (data == null) return null;

  if (data is Map) {
    final errorObj = data['error'];
    if (errorObj is Map && errorObj['message'] is String) {
      return (errorObj['message'] as String).trim();
    }
    if (data['message'] is String) {
      return (data['message'] as String).trim();
    }
    return null;
  }

  if (data is String) {
    final raw = data.trim();
    if (raw.isEmpty) return null;

    try {
      final decoded = jsonDecode(raw);
      return _extractApiMessage(decoded);
    } catch (_) {
      return raw;
    }
  }

  return null;
}
