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

import Foundation
import RookSDK

struct ActivityEventMapper {
  
  private let dateHelper: DateHelper = DateHelper()
  
  func map(event: RookActivityEvent) -> [String: Any?] {
    var dictionary: [String: Any?] = [:]
    dictionary.updateValue(dateHelper.getISO8601StringDate(date: event.dateTime), forKey: "dateTime")
    dictionary.updateValue(event.sourcesOfData, forKey: "sourcesOfData")
    dictionary.updateValue(dateHelper.getISO8601StringDate(date: event.activityStartTimeDateTime), forKey: "activityStartTimeDateTime")
    dictionary.updateValue(dateHelper.getISO8601StringDate(date: event.activityEndTimeDateTime), forKey: "activityEndTimeDateTime")
    dictionary.updateValue(event.activeSeconds, forKey: "activityDurationSeconds")
    dictionary.updateValue(event.activityTypeName, forKey: "activityTypeName")
    dictionary.updateValue(event.activeSeconds, forKey: "activeSeconds")
    dictionary.updateValue(event.restSeconds, forKey: "restSeconds")
    dictionary.updateValue(event.lowIntensitySeconds, forKey: "lowIntensitySeconds")
    dictionary.updateValue(event.moderateIntensitySeconds, forKey: "moderateIntensitySeconds")
    dictionary.updateValue(event.vigorousIntensitySeconds, forKey: "vigorousIntensitySeconds")
    dictionary.updateValue(event.inactivitySeconds, forKey: "inactivitySeconds")
    dictionary.updateValue(event.continuousInactivePeriodsNumber, forKey: "continuousInactivePeriodsNumber")
    dictionary.updateValue(event.activityStrainLevelNumber, forKey: "activityStrainLevelNumber")
    dictionary.updateValue(event.activityWorkKilojoules, forKey: "activityWorkKilojoules")
    dictionary.updateValue(event.activityEnergyKilojoules, forKey: "activityEnergyKilojoules")
    dictionary.updateValue(event.activityEnergyPlannedKilojoules, forKey: "activityEnergyPlannedKilojoules")
    dictionary.updateValue(event.caloriesNetIntakeKilocalories, forKey: "caloriesNetIntakeKilocalories")
    dictionary.updateValue(event.caloriesExpenditureKilocalories, forKey: "caloriesExpenditureKilocalories")
    dictionary.updateValue(event.caloriesNetActiveKilocalories, forKey: "caloriesNetActiveKilocalories")
    dictionary.updateValue(event.caloriesBasalMetabolicRateKilocalories, forKey: "caloriesBasalMetabolicRateKilocalories")
    dictionary.updateValue(event.fatPercentageOfCaloriesPercentage, forKey: "fatPercentageOfCaloriesPercentage")
    dictionary.updateValue(event.carbohydratePercentageOfCaloriesPercentage, forKey: "carbohydratePercentageOfCaloriesPercentage")
    dictionary.updateValue(event.proteinPercentageOfCaloriesPercentage, forKey: "proteinPercentageOfCaloriesPercentage")
    dictionary.updateValue(event.stepsNumber, forKey: "stepsNumber")
    dictionary.updateValue(event.walkedDistanceMeters, forKey: "walkedDistanceMeters")
    dictionary.updateValue(event.traveledDistanceMeters, forKey: "traveledDistanceMeters")
    dictionary.updateValue(event.floorsClimbedNumber, forKey: "floorsClimbedNumber")
    dictionary.updateValue(event.elevationAvgAltitudeMeters, forKey: "elevationAvgAltitudeMeters")
    dictionary.updateValue(event.elevationMinimumAltitudeMeters, forKey: "elevationMinimumAltitudeMeters")
    dictionary.updateValue(event.elevationMaxAltitudeMeters, forKey: "elevationMaxAltitudeMeters")
    dictionary.updateValue(event.elevationLossActualAltitudeMeters, forKey: "elevationLossActualAltitudeMeters")
    dictionary.updateValue(event.elevationGainActualAltitudeMeters, forKey: "elevationGainActualAltitudeMeters")
    dictionary.updateValue(event.elevationPlannedGainMeters, forKey: "elevationPlannedGainMeters")
    dictionary.updateValue(event.swimmingNumStrokesNumber, forKey: "swimmingNumStrokesNumber")
    dictionary.updateValue(event.swimmingNumLapsNumber, forKey: "swimmingNumLapsNumber")
    dictionary.updateValue(event.swimmingPoolLengthMeters, forKey: "swimmingPoolLengthMeters")
    dictionary.updateValue(event.swimmingTotalDistanceMeters, forKey: "swimmingTotalDistanceMeters")
    dictionary.updateValue(event.hrMaxBPM, forKey: "hrMaxBPM")
    dictionary.updateValue(event.hrMinimumBPM, forKey: "hrMinimumBPM")
    dictionary.updateValue(event.hrAvgBPM, forKey: "hrAvgBPM")
    dictionary.updateValue(event.hrRestingBPM, forKey: "hrRestingBPM")
    dictionary.updateValue(event.hrvAvgRmssdNumber, forKey: "hrvAvgRmssdNumber")
    dictionary.updateValue(event.hrvAvgSdnnNumber, forKey: "hrvAvgSdnnNumber")
    dictionary.updateValue(event.speedNormalizedMetersPerSecond, forKey: "speedNormalizedMetersPerSecond")
    dictionary.updateValue(event.speedAvgMetersPerSecond, forKey: "speedAvgMetersPerSecond")
    dictionary.updateValue(event.speedMaxMetersPerSecond, forKey: "speedMaxMetersPerSecond")
    dictionary.updateValue(event.paceAvgMinutesPerKilometer, forKey: "paceAvgMinutesPerKilometer")
    dictionary.updateValue(event.paceMaxMinutesPerKilometer, forKey: "paceMaxMinutesPerKilometer")
    dictionary.updateValue(event.cadenceAvgRPM, forKey: "cadenceAvgRPM")
    dictionary.updateValue(event.cadenceMaxRPM, forKey: "cadenceMaxRPM")
    dictionary.updateValue(event.torqueAvgNewtonMeters, forKey: "torqueAvgNewtonMeters")
    dictionary.updateValue(event.torqueMaxNewtonMeters, forKey: "torqueMaxNewtonMeters")
    dictionary.updateValue(event.powerAvgWattsNumber, forKey: "powerAvgWattsNumber")
    dictionary.updateValue(event.powerMaxWattsNumber, forKey: "powerMaxWattsNumber")
    dictionary.updateValue(event.positionPolylineMapDataSummaryString, forKey: "positionPolylineMapDataSummaryString")
    dictionary.updateValue(event.saturationAvgPercentage, forKey: "saturationAvgPercentage")
    dictionary.updateValue(event.vo2MaxMlPerMinPerKg, forKey: "vo2MaxMlPerMinPerKg")
    dictionary.updateValue(event.stressAtRESTDurationSeconds, forKey: "stressAtRESTDurationSeconds")
    dictionary.updateValue(event.stressDurationSeconds, forKey: "stressDurationSeconds")
    dictionary.updateValue(event.lowStressDurationSeconds, forKey: "lowStressDurationSeconds")
    dictionary.updateValue(event.mediumStressDurationSeconds, forKey: "mediumStressDurationSeconds")
    dictionary.updateValue(event.highStressDurationSeconds, forKey: "highStressDurationSeconds")
    dictionary.updateValue(event.stressAvgLevelNumber, forKey: "stressAvgLevelNumber")
    dictionary.updateValue(event.stressMaxLevelNumber, forKey: "stressMaxLevelNumber")
    dictionary.updateValue(event.appleWorkoutIdentifier, forKey: "appleWorkoutIdentifier")
    dictionary.updateValue(event.appleDistanceCyclingMeters, forKey: "appleDistanceCyclingMeters")
    // MARK:  Granular or Object
    dictionary.updateValue(event.activityLevelGranularDataNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "activityLevel": $0.activityLevel
      ]
    }), forKey: "activityLevelGranularDataNumber")
    dictionary.updateValue(event.stepsGranularDataStepsPerMin?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "steps": $0.steps
      ]
    }), forKey: "stepsGranularDataStepsPerMin")
    dictionary.updateValue(event.traveledDistanceGranularDataMeters?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "traveledDistanceMeters": $0.traveledDistanceMeters,
      ]
    }), forKey: "traveledDistanceGranularDataMeters")
    dictionary.updateValue(event.floorsClimbedGranularDataFloorsNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "floorsClimbed": $0.floorsClimbed
      ]
    }), forKey: "floorsClimbedGranularDataFloorsNumber")
    dictionary.updateValue(event.elevationGranularDataMeters?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "elevationChange": $0.elevationChange
      ]
    }), forKey: "elevationGranularDataMeters")
    dictionary.updateValue(event.swimmingDistanceGranularDataMeters?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "swimmingDistanceMeters": $0.swimmingDistanceMeters
      ]
    }), forKey: "swimmingDistanceGranularDataMeters")
    dictionary.updateValue(event.hrGranularDataBPM?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "hrBPM": $0.hrBPM
      ]
    }), forKey: "hrGranularDataBPM")
    dictionary.updateValue(event.hrvSdnnGranularDataNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "hrvSDNN": $0.hrvSDNN
      ]
    }), forKey: "hrvSdnnGranularDataNumber")
    dictionary.updateValue(event.hrvRmssdGranularDataNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "hrvRmssd": $0.hrvRmssd
      ]
    }), forKey: "hrvRmssdGranularDataNumber")
    dictionary.updateValue(event.speedGranularDataMetersPerSecond?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "speedMetersPerSecond": $0.speedMetersPerSecond
      ]
    }), forKey: "speedGranularDataMetersPerSecond")
    dictionary.updateValue(mapVelocity(event.velocityVectorAvgSpeedAndDirection),
                           forKey: "velocityVectorAvgSpeedAndDirection")
    dictionary.updateValue(mapVelocity(event.velocityVectorMaxSpeedAndDirection),
                           forKey: "velocityVectorMaxSpeedAndDirection")
    dictionary.updateValue(event.cadenceGranularDataRPM?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "cadenceRPM": $0.cadenceRPM
      ]
    }), forKey: "cadenceGranularDataRPM")
    dictionary.updateValue(event.torqueGranularDataNewtonMeters?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "torqueNewtonMeters": $0.torqueNewtonMeters
      ]
    }), forKey: "torqueGranularDataNewtonMeters")
    dictionary.updateValue(event.lapGranularDataLapsNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "laps": $0.laps
      ]
    }), forKey: "lapGranularDataLapsNumber")
    dictionary.updateValue(event.powerGranularDataWattsNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "powerWatts": $0.powerWatts
      ]
    }), forKey: "powerGranularDataWattsNumber")
    dictionary.updateValue(mapPosition(position: event.positionStartLatLngDeg), forKey: "positionStartLatLngDeg")
    dictionary.updateValue(mapPosition(position: event.positionCentroidLatLngDeg), forKey: "positionCentroidLatLngDeg")
    dictionary.updateValue(mapPosition(position: event.positionEndLatLngDeg), forKey: "positionEndLatLngDeg")
    dictionary.updateValue(event.positionGranularDataLatLngDeg?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "lat": $0.lat,
        "lng": $0.lng,
      ]
    }), forKey: "positionGranularDataLatLngDeg")
    dictionary.updateValue(event.saturationGranularDataPercentage?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "saturationPercentage": $0.saturationPercentage
      ]
    }), forKey: "saturationGranularDataPercentage")
    dictionary.updateValue(event.vo2GranularDataMlPerMin?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "vo2MlPerMinPerKg": $0.vo2MlPerMinPerKg
      ]
    }), forKey: "vo2GranularDataMlPerMin")
    dictionary.updateValue(event.tssGranularData1_500_ScoreNumber?.map({
      [
        "dateTime": dateHelper.getISO8601StringDate(date: $0.dateTime),
        "intervalDurationSeconds": $0.intervalDurationSeconds,
        "tss1_500_Score": $0.tss1_500_Score,
      ]
    }), forKey: "tssGranularData1_500_ScoreNumber")
    return dictionary
  }

  private func mapPosition(position: [RookPositionLatLng]?) -> [String: Any]? {
    if let item: RookPositionLatLng = position?.first {
      return [
        "lat": item.lat,
        "lng": item.lng
      ]
    } else {
      return nil
    }
  }

  private func mapVelocity(_ velocity: [RookVelocityVectorSpeed]?) -> [String: Any]? {
    if let item: RookVelocityVectorSpeed = velocity?.first {
      return [
        "direction": item.direction,
        "speedMetersPerSecond": item.speedMetersPerSecond
      ]
    } else {
      return nil
    }
  }
}
