import 'package:dio/dio.dart';
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart';
import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/total_energy_consumption_service.dart';
import 'package:syncrow_web/services/api/api_exception.dart';
import 'package:syncrow_web/services/api/http_service.dart';

class RemoteTotalEnergyConsumptionService implements TotalEnergyConsumptionService {
  const RemoteTotalEnergyConsumptionService(this._httpService);

  final HTTPService _httpService;

  static const _defaultErrorMessage = 'Failed to load total energy consumption';

  @override
  Future<List<EnergyDataModel>> load(
    GetTotalEnergyConsumptionParam param,
  ) async {
    try {
      final response = await _httpService.get(
        path: '/power-clamp/historical',
        showServerMessage: true,
        queryParameters: param.toJson(),
        expectedResponseModel: _TotalEnergyConsumptionResponseMapper.map,
      );

      return response;
    } on DioException catch (e) {
      final message = e.response?.data as Map<String, dynamic>?;
      final error = message?['error'] as Map<String, dynamic>?;
      final errorMessage = error?['error'] as String? ?? '';
      final formattedErrorMessage = [_defaultErrorMessage, errorMessage].join(': ');
      throw APIException(formattedErrorMessage);
    } catch (e) {
      final formattedErrorMessage = [_defaultErrorMessage, '$e'].join(': ');
      throw APIException(formattedErrorMessage);
    }
  }
}

abstract final class _TotalEnergyConsumptionResponseMapper {
  const _TotalEnergyConsumptionResponseMapper._();

  static List<EnergyDataModel> map(dynamic data) {
    final json = data as Map<String, dynamic>? ?? {};
    final dailyData = json['data'] as List<dynamic>? ?? [];

    return dailyData.map((dayData) {
      final date = dayData['date'] as String;
      final energyValue = double.tryParse(
            dayData['total_energy_consumed_kw'] as String? ?? '0',
          ) ??
          0.0;

      return EnergyDataModel(
        date: DateTime.parse(date),
        value: energyValue,
      );
    }).toList();
  }
}

class DividedTotalEnergyConsumptionDecorator
    implements TotalEnergyConsumptionService {
  const DividedTotalEnergyConsumptionDecorator(this._decoratee);

  final TotalEnergyConsumptionService _decoratee;
  @override
  Future<List<EnergyDataModel>> load(
    GetTotalEnergyConsumptionParam param,
  ) async {
    final result = await _decoratee.load(param);
    final dividedResult = result.map((e) {
      return EnergyDataModel(
        date: e.date,
        value: e.value / 100,
      );
    });
    return dividedResult.toList();
  }
}
