//
//  BodySummaryDictionaryMapper.swift
//  Plugin
//
//  Created by Francisco Guerrero Escamilla on 07/10/25.
//  Copyright © 2025 Max Lynch. All rights reserved.
//

import Foundation
import RookSDK

struct BodySummaryDictionaryMapper {

  // MARK:  Properties

  private let dateHelper: DateHelper = DateHelper()

  // MARK:  Implementation

  func map(_ summary: RookBodySummary) -> [String: Any?] {
    var dictionary: [String: Any?] = [:]
    dictionary.updateValue(dateHelper.getISO8601StringDate(date: summary.dateTime), forKey: "dateTime")
    dictionary.updateValue(summary.bodyHealthScore, forKey: "bodyHealthScore")
    dictionary.updateValue(summary.waistCircumferenceCMNumber, forKey: "waistCircumferenceCMNumber")
    dictionary.updateValue(summary.hipCircumferenceCMNumber, forKey: "hipCircumferenceCMNumber")
    dictionary.updateValue(summary.chestCircumferenceCMNumber, forKey: "chestCircumferenceCMNumber")
    dictionary.updateValue(summary.boneCompositionPercentageNumber, forKey: "boneCompositionPercentageNumber")
    dictionary.updateValue(summary.muscleCompositionPercentageNumber, forKey: "muscleCompositionPercentageNumber")
    dictionary.updateValue(summary.waterCompositionPercentageNumber, forKey: "waterCompositionPercentageNumber")
    dictionary.updateValue(summary.weightKgNumber, forKey: "weightKgNumber")
    dictionary.updateValue(summary.heightCMNumber, forKey: "heightCMNumber")
    dictionary.updateValue(summary.bmiNumber, forKey: "bmiNumber")
    dictionary.updateValue(summary.bloodGlucoseDayAvgMgPerDLNumber, forKey: "bloodGlucoseDayAvgMgPerDLNumber")
    dictionary.updateValue(summary.bloodGlucoseGranularDataMgPerDL?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "bloodGlucoseMgPerDL": $0.bloodGlucoseMgPerDL
      ]
    }), forKey: "bloodGlucoseGranularDataMgPerDL")
    dictionary.updateValue(mapPressure(summary.bloodPressureDayAvgSystolicDiastolicBpNumber), forKey: "bloodPressureDayAvgSystolicDiastolicBpNumber")
    dictionary.updateValue(summary.bloodPressureGranularDataSystolicDiastolicBpNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "systolicBp": $0.systolicBp,
        "diastolicBp": $0.diastolicBp
      ]
    }), forKey: "bloodPressureGranularDataSystolicDiastolicBpNumber")
    dictionary.updateValue(summary.waterTotalConsumptionMlNumber, forKey: "waterTotalConsumptionMlNumber")
    dictionary.updateValue(summary.hydrationAmountGranularDataMlNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "hydrationAmountMl": $0.hydrationAmountMl
      ]
    }), forKey: "hydrationAmountGranularDataMlNumber")
    dictionary.updateValue(summary.hydrationLevelGranularDataPercentageNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "hydrationLevelPercentage": $0.hydrationLevelPercentage
      ]
    }), forKey: "hydrationLevelGranularDataPercentageNumber")
    dictionary.updateValue(summary.hrMaxBPM, forKey: "hrMaxBPM")
    dictionary.updateValue(summary.hrMinimumBPM, forKey: "hrMinimumBPM")
    dictionary.updateValue(summary.hrAvgBPM, forKey: "hrAvgBPM")
    dictionary.updateValue(summary.hrRestingBPM, forKey: "hrRestingBPM")
    dictionary.updateValue(summary.hrGranularDataBPM?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "hrBPM": $0.hrBPM
      ]
    }), forKey: "hrGranularDataBPM")
    dictionary.updateValue(summary.hrvAvgRmssdNumber, forKey: "hrvAvgRmssdNumber")
    dictionary.updateValue(summary.hrvAvgSdnnNumber, forKey: "hrvAvgSdnnNumber")
    dictionary.updateValue(summary.hrvSdnnGranularDataNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "hrvSDNN": $0.hrvSDNN
      ]
    }), forKey: "hrvSdnnGranularDataNumber")
    dictionary.updateValue(summary.hrvRmssdGranularDataNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "hrvRmssd": $0.hrvRmssd
      ]
    }), forKey: "hrvRmssdGranularDataNumber")
    dictionary.updateValue(summary.moodMinimumScale, forKey: "moodMinimumScale")
    dictionary.updateValue(summary.moodAvgScale, forKey: "moodAvgScale")
    dictionary.updateValue(summary.moodGranularDataScale?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "moodScale": $0.moodScale,
      ]
    }), forKey: "moodGranularDataScale")
    dictionary.updateValue(summary.moodMaxScale, forKey: "moodMaxScale")
    dictionary.updateValue(summary.moodDeltaScale, forKey: "moodDeltaScale")
    dictionary.updateValue(summary.foodIntakeNumber, forKey: "foodIntakeNumber")
    dictionary.updateValue(summary.caloriesIntakeNumber, forKey: "caloriesIntakeNumber")
    dictionary.updateValue(summary.proteinIntakeGNumber, forKey: "proteinIntakeGNumber")
    dictionary.updateValue(summary.sugarIntakeGNumber, forKey: "sugarIntakeGNumber")
    dictionary.updateValue(summary.fatIntakeGNumber, forKey: "fatIntakeGNumber")
    dictionary.updateValue(summary.transFatIntakeGNumber, forKey: "transFatIntakeGNumber")
    dictionary.updateValue(summary.carbohydratesIntakeGNumber, forKey: "carbohydratesIntakeGNumber")
    dictionary.updateValue(summary.fiberIntakeGNumber, forKey: "fiberIntakeGNumber")
    dictionary.updateValue(summary.alcoholIntakeGNumber, forKey: "alcoholIntakeGNumber")
    dictionary.updateValue(summary.sodiumIntakeMgNumber, forKey: "sodiumIntakeMgNumber")
    dictionary.updateValue(summary.cholesterolIntakeMgNumber, forKey: "cholesterolIntakeMgNumber")
    dictionary.updateValue(summary.saturationAvgPercentage, forKey: "saturationAvgPercentage")
    dictionary.updateValue(summary.saturationGranularDataPercentage?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "saturationPercentage": $0.saturationPercentage
      ]
    }), forKey: "saturationGranularDataPercentage")
    dictionary.updateValue(summary.vo2MaxMlPerMinPerKg, forKey: "vo2MaxMlPerMinPerKg")
    dictionary.updateValue(summary.vo2GranularDataLiterPerMin?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "vo2MlPerMinPerKg": $0.vo2MlPerMinPerKg
      ]
    }), forKey: "vo2GranularDataLiterPerMin")
    dictionary.updateValue(mapTemperature(summary.temperatureMinimumCelsius), forKey: "temperatureMinimumCelsius")
    dictionary.updateValue(mapTemperature(summary.temperatureAvgCelsius), forKey: "temperatureAvgCelsius")
    dictionary.updateValue(mapTemperature(summary.temperatureMaxCelsius), forKey: "temperatureMaxCelsius")
    dictionary.updateValue(mapTemperature(summary.temperatureDeltaCelsius), forKey: "temperatureDeltaCelsius")
    dictionary.updateValue(summary.temperatureGranularDataCelsius?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "temperatureCelsius": $0.temperatureCelsius,
        "measurementType": $0.measurementType,
      ]
    }), forKey: "temperatureGranularDataCelsius")
    dictionary.updateValue(summary.uvExposureMax, forKey: "uvExposureMax")
    dictionary.updateValue(summary.uvExposureAvg, forKey: "uvExposureAvg")
    dictionary.updateValue(summary.uvExposureMin, forKey: "uvExposureMin")
    dictionary.updateValue(summary.uvExposureSeconds, forKey: "uvExposureSeconds")
    return dictionary
  }

  private func mapTemperature(_ object: [RookTemperature]?) -> [String: Any]? {
    if let item: RookTemperature = object?.first {
      return [
        "temperatureCelsius": item.temperatureCelsius,
        "measurementType": item.measurementType
      ]
    } else {
      return nil
    }
  }

  private func mapPressure(_ object: [RookBloodPressureSystolicDiastolic]?) -> [String: Any]? {
    if let item: RookBloodPressureSystolicDiastolic = object?.first {
      return [
        "diastolicBp": item.diastolicBp,
        "systolicBp": item.systolicBp
      ]
    } else {
      return nil
    }
  }
}
