//
//  ChargeInsightsStore.swift
//  USB Meter
//
//  Created by Codex on 10/04/2026.
//

import CoreData
import Foundation

final class ChargeInsightsStore {
    private enum EntityName {
        static let chargedDevice = "ChargedDevice"
        static let chargeSession = "ChargeSession"
        static let chargeCheckpoint = "ChargeCheckpoint"
        static let chargeSessionSample = "ChargeSessionSample"
    }

    private enum MeterAssignmentKind {
        case chargedDevice
        case charger

        var expectsChargerClass: Bool {
            switch self {
            case .chargedDevice:
                return false
            case .charger:
                return true
            }
        }
    }

    private static let maximumChargeSessionDuration: TimeInterval = 12 * 60 * 60
    private static let persistedSamplesPerHour = 360
    private static let aggregatedSampleBucketDuration = 3600.0 / Double(persistedSamplesPerHour)

    private let context: NSManagedObjectContext
    private let stopDetectionHoldDuration: TimeInterval = 20
    private let maximumLiveIntegrationGap: TimeInterval = 90
    private let activeSessionSaveInterval: TimeInterval = 60
    private let aggregatedSampleSaveInterval: TimeInterval = 30
    private let counterDecreaseTolerance = 0.002
    private let completionConfirmationCooldown: TimeInterval = 15 * 60
    private let pausedSessionTimeout: TimeInterval = 10 * 60
    private let defaultCompletionPercentThreshold = 95.0
    private let completionContradictionTolerancePercent = 2.0
    private let minimumWirelessEfficiencyFactor = 0.35
    private let maximumWirelessEfficiencyFactor = 0.95
    private let lowWirelessEfficiencyThreshold = 0.72
    private let unresolvedFlatBatteryPercent = -1.0

    init(context: NSManagedObjectContext) {
        self.context = context
    }

    func refreshContext() {
        context.performAndWait {
            context.processPendingChanges()
        }
    }

    func resetContext() {
        context.performAndWait {
            context.reset()
        }
    }

    @discardableResult
    func flushPendingChanges() -> Bool {
        var didSave = false
        context.performAndWait {
            context.processPendingChanges()
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func completeExpiredOpenSessions(referenceDate: Date = Date()) -> Bool {
        var didSave = false

        context.performAndWait {
            let expiredSessions = fetchOpenSessionObjects().compactMap { session -> NSManagedObject? in
                guard automaticCompletionDate(for: session, referenceDate: referenceDate) != nil else {
                    return nil
                }
                return session
            }
            guard expiredSessions.isEmpty == false else {
                return
            }

            var chargedDeviceIDsToRefresh = Set<String>()
            for session in expiredSessions {
                guard let completionDate = automaticCompletionDate(for: session, referenceDate: referenceDate) else {
                    continue
                }
                finishSession(
                    session,
                    observedAt: completionDate,
                    finalBatteryPercent: nil,
                    status: .completed
                )
                if let chargedDeviceID = stringValue(session, key: "chargedDeviceID") {
                    chargedDeviceIDsToRefresh.insert(chargedDeviceID)
                }
            }

            guard saveContext() else {
                return
            }

            for chargedDeviceID in chargedDeviceIDsToRefresh {
                refreshDerivedMetrics(forChargedDeviceID: chargedDeviceID)
            }
            didSave = saveContext()
        }

        return didSave
    }

    @discardableResult
    func createDevice(
        name: String,
        deviceClass: ChargedDeviceClass,
        templateID: String?,
        chargingStateAvailability: ChargingStateAvailability,
        supportsWiredCharging: Bool,
        supportsWirelessCharging: Bool,
        wirelessChargingProfile: WirelessChargingProfile,
        configuredCompletionCurrents: [ChargeSessionKind: Double],
        notes: String?,
        assignTo meterMACAddress: String?
    ) -> Bool {
        guard deviceClass.kind == .device else { return false }
        let normalizedName = normalizedText(name)
        let normalizedChargingStateAvailability = deviceClass.normalizedChargingStateAvailability(chargingStateAvailability)
        let normalizedChargingSupport = deviceClass.normalizedChargingSupport(
            supportsWiredCharging: supportsWiredCharging,
            supportsWirelessCharging: supportsWirelessCharging
        )
        let normalizedTemplateID = normalizedTemplateID(templateID, kind: .device)
        guard !normalizedName.isEmpty else { return false }
        guard normalizedChargingSupport.wired || normalizedChargingSupport.wireless else { return false }

        var didSave = false
        context.performAndWait {
            guard let entity = NSEntityDescription.entity(forEntityName: EntityName.chargedDevice, in: context) else {
                return
            }

            let object = NSManagedObject(entity: entity, insertInto: context)
            let now = Date()
            object.setValue(UUID().uuidString, forKey: "id")
            object.setValue(normalizedName, forKey: "name")
            object.setValue(deviceClass.rawValue, forKey: "deviceClassRawValue")
            object.setValue(normalizedTemplateID, forKey: "deviceTemplateID")
            object.setValue(normalizedChargingStateAvailability.rawValue, forKey: "chargingStateAvailabilityRawValue")
            object.setValue(normalizedChargingStateAvailability.supportsChargingWhileOff, forKey: "supportsChargingWhileOff")
            object.setValue(normalizedChargingSupport.wired, forKey: "supportsWiredCharging")
            object.setValue(normalizedChargingSupport.wireless, forKey: "supportsWirelessCharging")
            object.setValue(wirelessChargingProfile.rawValue, forKey: "wirelessChargingProfileRawValue")
            object.setValue(encodedCompletionCurrents(configuredCompletionCurrents), forKey: "configuredCompletionCurrentsRawValue")
            object.setValue(legacyConfiguredCompletionCurrent(for: configuredCompletionCurrents, chargingTransportMode: .wired), forKey: "wiredChargeCompletionCurrentAmps")
            object.setValue(legacyConfiguredCompletionCurrent(for: configuredCompletionCurrents, chargingTransportMode: .wireless), forKey: "wirelessChargeCompletionCurrentAmps")
            object.setValue(normalizedOptionalText(notes), forKey: "notes")
            object.setValue(generateQRIdentifier(), forKey: "qrIdentifier")
            object.setValue(normalizedOptionalText(meterMACAddress), forKey: "lastAssociatedMeterMAC")
            object.setValue(now, forKey: "createdAt")
            object.setValue(now, forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func createCharger(
        name: String,
        chargerType: ChargerType,
        notes: String?,
        assignTo meterMACAddress: String?
    ) -> Bool {
        let normalizedName = normalizedText(name)
        guard !normalizedName.isEmpty else { return false }

        var didSave = false
        context.performAndWait {
            guard let entity = NSEntityDescription.entity(forEntityName: EntityName.chargedDevice, in: context) else {
                return
            }

            let object = NSManagedObject(entity: entity, insertInto: context)
            let now = Date()
            object.setValue(UUID().uuidString, forKey: "id")
            object.setValue(normalizedName, forKey: "name")
            object.setValue(ChargedDeviceClass.charger.rawValue, forKey: "deviceClassRawValue")
            object.setValue(nil, forKey: "deviceTemplateID")
            object.setValue(ChargingStateAvailability.onOnly.rawValue, forKey: "chargingStateAvailabilityRawValue")
            object.setValue(false, forKey: "supportsChargingWhileOff")
            object.setValue(false, forKey: "supportsWiredCharging")
            object.setValue(true, forKey: "supportsWirelessCharging")
            if object.entity.attributesByName["chargerTypeRawValue"] != nil {
                object.setValue(chargerType.rawValue, forKey: "chargerTypeRawValue")
            }
            object.setValue(chargerType.wirelessChargingProfile.rawValue, forKey: "wirelessChargingProfileRawValue")
            object.setValue(encodedCompletionCurrents([:]), forKey: "configuredCompletionCurrentsRawValue")
            object.setValue(nil, forKey: "wiredChargeCompletionCurrentAmps")
            object.setValue(nil, forKey: "wirelessChargeCompletionCurrentAmps")
            object.setValue(normalizedOptionalText(notes), forKey: "notes")
            object.setValue(generateQRIdentifier(), forKey: "qrIdentifier")
            object.setValue(normalizedOptionalText(meterMACAddress), forKey: "lastAssociatedMeterMAC")
            object.setValue(now, forKey: "createdAt")
            object.setValue(now, forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func updateDevice(
        id: UUID,
        name: String,
        deviceClass: ChargedDeviceClass,
        templateID: String?,
        chargingStateAvailability: ChargingStateAvailability,
        supportsWiredCharging: Bool,
        supportsWirelessCharging: Bool,
        wirelessChargingProfile: WirelessChargingProfile,
        configuredCompletionCurrents: [ChargeSessionKind: Double],
        notes: String?
    ) -> Bool {
        guard deviceClass.kind == .device else { return false }
        let normalizedName = normalizedText(name)
        let normalizedChargingStateAvailability = deviceClass.normalizedChargingStateAvailability(chargingStateAvailability)
        let normalizedChargingSupport = deviceClass.normalizedChargingSupport(
            supportsWiredCharging: supportsWiredCharging,
            supportsWirelessCharging: supportsWirelessCharging
        )
        let normalizedTemplateID = normalizedTemplateID(templateID, kind: .device)
        guard !normalizedName.isEmpty else { return false }
        guard normalizedChargingSupport.wired || normalizedChargingSupport.wireless else { return false }

        var didSave = false
        context.performAndWait {
            guard let object = fetchChargedDeviceObject(id: id.uuidString) else {
                return
            }
            guard isChargerObject(object) == false else {
                return
            }

            let previousSupportsChargingWhileOff = boolValue(object, key: "supportsChargingWhileOff")
            let previousChargingStateAvailability = self.chargingStateAvailability(for: object)
            let previousSupportsWiredCharging = self.supportsWiredCharging(for: object)
            let previousSupportsWirelessCharging = self.supportsWirelessCharging(for: object)
            let now = Date()

            object.setValue(normalizedName, forKey: "name")
            object.setValue(deviceClass.rawValue, forKey: "deviceClassRawValue")
            object.setValue(normalizedTemplateID, forKey: "deviceTemplateID")
            object.setValue(normalizedChargingStateAvailability.rawValue, forKey: "chargingStateAvailabilityRawValue")
            object.setValue(normalizedChargingStateAvailability.supportsChargingWhileOff, forKey: "supportsChargingWhileOff")
            object.setValue(normalizedChargingSupport.wired, forKey: "supportsWiredCharging")
            object.setValue(normalizedChargingSupport.wireless, forKey: "supportsWirelessCharging")
            object.setValue(wirelessChargingProfile.rawValue, forKey: "wirelessChargingProfileRawValue")
            object.setValue(encodedCompletionCurrents(configuredCompletionCurrents), forKey: "configuredCompletionCurrentsRawValue")
            object.setValue(legacyConfiguredCompletionCurrent(for: configuredCompletionCurrents, chargingTransportMode: .wired), forKey: "wiredChargeCompletionCurrentAmps")
            object.setValue(legacyConfiguredCompletionCurrent(for: configuredCompletionCurrents, chargingTransportMode: .wireless), forKey: "wirelessChargeCompletionCurrentAmps")
            object.setValue(normalizedOptionalText(notes), forKey: "notes")
            object.setValue(now, forKey: "updatedAt")

            let supportsChargingWhileOff = normalizedChargingStateAvailability.supportsChargingWhileOff
            let shouldRecalculateSessionCapacity = previousSupportsChargingWhileOff != supportsChargingWhileOff
            let shouldRefreshActiveSessions = shouldRecalculateSessionCapacity
                || previousChargingStateAvailability != normalizedChargingStateAvailability
                || previousSupportsWiredCharging != normalizedChargingSupport.wired
                || previousSupportsWirelessCharging != normalizedChargingSupport.wireless

            if shouldRecalculateSessionCapacity || shouldRefreshActiveSessions {
                let sessions = fetchSessions(forChargedDeviceID: id.uuidString)
                for session in sessions {
                    let isOpen = statusValue(session, key: "statusRawValue")?.isOpen == true

                    if shouldRecalculateSessionCapacity {
                        session.setValue(supportsChargingWhileOff, forKey: "supportsChargingWhileOff")
                        updateCapacityEstimate(for: session)
                        session.setValue(now, forKey: "updatedAt")
                    }

                    guard isOpen, shouldRefreshActiveSessions else {
                        continue
                    }

                    let resolvedSessionChargingTransportMode = resolvedPreferredChargingTransportMode(
                        chargingTransportMode(for: session),
                        supportsWiredCharging: normalizedChargingSupport.wired,
                        supportsWirelessCharging: normalizedChargingSupport.wireless
                    )
                    let resolvedSessionChargingStateMode = resolvedChargingStateMode(
                        chargingStateMode(for: session),
                        availability: normalizedChargingStateAvailability
                    )
                    let charger = stringValue(session, key: "chargerID").flatMap(fetchChargedDeviceObject(id:))

                    session.setValue(supportsChargingWhileOff, forKey: "supportsChargingWhileOff")
                    session.setValue(resolvedSessionChargingTransportMode.rawValue, forKey: "chargingTransportRawValue")
                    session.setValue(resolvedSessionChargingStateMode.rawValue, forKey: "chargingStateRawValue")
                    session.setValue(
                        resolvedStopThreshold(
                            for: object,
                            chargingTransportMode: resolvedSessionChargingTransportMode,
                            chargingStateMode: resolvedSessionChargingStateMode,
                            charger: charger,
                            fallback: optionalDoubleValue(session, key: "stopThresholdAmps")
                        ) ?? 0,
                        forKey: "stopThresholdAmps"
                    )
                    session.setValue(now, forKey: "updatedAt")
                    updateCapacityEstimate(for: session)
                }
            }

            refreshDerivedMetrics(forChargedDeviceID: id.uuidString)
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func updateCharger(
        id: UUID,
        name: String,
        chargerType: ChargerType,
        notes: String?
    ) -> Bool {
        let normalizedName = normalizedText(name)
        guard !normalizedName.isEmpty else { return false }

        var didSave = false
        context.performAndWait {
            guard let object = fetchChargedDeviceObject(id: id.uuidString) else {
                return
            }
            guard isChargerObject(object) else {
                return
            }

            object.setValue(normalizedName, forKey: "name")
            object.setValue(nil, forKey: "deviceTemplateID")
            object.setValue(ChargingStateAvailability.onOnly.rawValue, forKey: "chargingStateAvailabilityRawValue")
            object.setValue(false, forKey: "supportsChargingWhileOff")
            object.setValue(false, forKey: "supportsWiredCharging")
            object.setValue(true, forKey: "supportsWirelessCharging")
            if object.entity.attributesByName["chargerTypeRawValue"] != nil {
                object.setValue(chargerType.rawValue, forKey: "chargerTypeRawValue")
            }
            object.setValue(chargerType.wirelessChargingProfile.rawValue, forKey: "wirelessChargingProfileRawValue")
            object.setValue(normalizedOptionalText(notes), forKey: "notes")
            object.setValue(Date(), forKey: "updatedAt")
            refreshDerivedMetrics(forChargedDeviceID: id.uuidString)
            didSave = saveContext()
        }

        return didSave
    }

    @discardableResult
    func assignChargedDevice(id: UUID, to meterMACAddress: String) -> Bool {
        assign(itemWithID: id, to: meterMACAddress, kind: .chargedDevice)
    }

    @discardableResult
    func assignCharger(id: UUID, to meterMACAddress: String) -> Bool {
        assign(itemWithID: id, to: meterMACAddress, kind: .charger)
    }

    @discardableResult
    private func assign(
        itemWithID id: UUID,
        to meterMACAddress: String,
        kind: MeterAssignmentKind
    ) -> Bool {
        let normalizedMAC = normalizedMACAddress(meterMACAddress)
        guard !normalizedMAC.isEmpty else { return false }

        var didSave = false
        context.performAndWait {
            guard let object = fetchChargedDeviceObject(id: id.uuidString) else {
                return
            }

            let isCharger = ChargedDeviceClass(rawValue: stringValue(object, key: "deviceClassRawValue") ?? "") == .charger
            guard isCharger == kind.expectsChargerClass else {
                return
            }

            let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargedDevice)
            request.predicate = NSPredicate(
                format: "lastAssociatedMeterMAC == %@ AND id != %@",
                normalizedMAC,
                id.uuidString
            )
            let previouslyAssignedDevices = (try? context.fetch(request)) ?? []
            for previousDevice in previouslyAssignedDevices {
                let previousIsCharger = ChargedDeviceClass(rawValue: stringValue(previousDevice, key: "deviceClassRawValue") ?? "") == .charger
                guard previousIsCharger == kind.expectsChargerClass else {
                    continue
                }
                previousDevice.setValue(nil, forKey: "lastAssociatedMeterMAC")
                previousDevice.setValue(Date(), forKey: "updatedAt")
            }

            object.setValue(normalizedMAC, forKey: "lastAssociatedMeterMAC")
            object.setValue(Date(), forKey: "updatedAt")

            if kind == .charger,
               let openSession = fetchOpenSessionObject(forMeterMACAddress: normalizedMAC),
               chargingTransportMode(for: openSession) == .wireless {
                openSession.setValue(id.uuidString, forKey: "chargerID")
                openSession.setValue(Date(), forKey: "updatedAt")
            }

            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func startSession(
        for snapshot: ChargingMonitorSnapshot,
        chargedDeviceID: UUID,
        chargerID: UUID?,
        chargingTransportMode: ChargingTransportMode,
        chargingStateMode: ChargingStateMode,
        autoStopEnabled: Bool,
        initialBatteryPercent: Double?,
        startsFromFlatBattery: Bool
    ) -> Bool {
        if let initialBatteryPercent,
           (initialBatteryPercent.isFinite == false || initialBatteryPercent < 0 || initialBatteryPercent > 100) {
            return false
        }

        var didSave = false
        context.performAndWait {
            guard let chargedDevice = fetchChargedDeviceObject(id: chargedDeviceID.uuidString) else {
                return
            }
            guard isChargerObject(chargedDevice) == false else {
                return
            }

            guard fetchOpenSessionObject(forMeterMACAddress: snapshot.meterMACAddress) == nil else {
                return
            }

            let resolvedChargingTransportMode = resolvedPreferredChargingTransportMode(
                chargingTransportMode,
                supportsWiredCharging: supportsWiredCharging(for: chargedDevice),
                supportsWirelessCharging: supportsWirelessCharging(for: chargedDevice)
            )
            let resolvedChargingStateMode = resolvedChargingStateMode(
                chargingStateMode,
                availability: chargingStateAvailability(for: chargedDevice)
            )
            let charger = resolvedChargingTransportMode == .wireless
                ? chargerID.flatMap { fetchChargedDeviceObject(id: $0.uuidString) }
                : nil
            if let charger, isChargerObject(charger) == false {
                return
            }
            guard resolvedChargingTransportMode == .wired || charger != nil else {
                return
            }
            let stopThreshold = resolvedStopThreshold(
                for: chargedDevice,
                chargingTransportMode: resolvedChargingTransportMode,
                chargingStateMode: resolvedChargingStateMode,
                charger: charger,
                fallback: snapshot.fallbackStopThresholdAmps > 0 ? snapshot.fallbackStopThresholdAmps : nil
            )
            guard let session = createSessionObject(
                for: chargedDevice,
                charger: charger,
                snapshot: snapshot,
                stopThreshold: stopThreshold,
                chargingTransportMode: resolvedChargingTransportMode,
                chargingStateMode: resolvedChargingStateMode,
                autoStopEnabled: autoStopEnabled
            ) else {
                return
            }

            if startsFromFlatBattery {
                session.setValue(unresolvedFlatBatteryPercent, forKey: "startBatteryPercent")
                session.setValue(nil, forKey: "endBatteryPercent")
            } else if let initialBatteryPercent {
                guard insertBatteryCheckpoint(
                    percent: initialBatteryPercent,
                    flag: .initial,
                    timestamp: snapshot.observedAt,
                    to: session
                ) != nil else {
                    return
                }
            }
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func pauseSession(id sessionID: UUID, observedAt: Date) -> Bool {
        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            guard statusValue(session, key: "statusRawValue") == .active else {
                return
            }

            session.setValue(ChargeSessionStatus.paused.rawValue, forKey: "statusRawValue")
            session.setValue(observedAt, forKey: "pausedAt")
            session.setValue(nil, forKey: "belowThresholdSince")
            clearCompletionConfirmationState(for: session)
            session.setValue(observedAt, forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func resumeSession(id sessionID: UUID, snapshot: ChargingMonitorSnapshot?) -> Bool {
        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            guard statusValue(session, key: "statusRawValue") == .paused else {
                return
            }

            let resumedAt = snapshot?.observedAt ?? Date()
            if let completionDate = automaticCompletionDate(for: session, referenceDate: resumedAt) {
                finishSession(
                    session,
                    observedAt: completionDate,
                    finalBatteryPercent: nil,
                    status: .completed
                )
                guard saveContext() else {
                    return
                }
                if let deviceID = stringValue(session, key: "chargedDeviceID") {
                    refreshDerivedMetrics(forChargedDeviceID: deviceID)
                    didSave = saveContext()
                } else {
                    didSave = true
                }
                return
            }

            session.setValue(ChargeSessionStatus.active.rawValue, forKey: "statusRawValue")
            session.setValue(nil, forKey: "pausedAt")
            session.setValue(nil, forKey: "belowThresholdSince")
            clearCompletionConfirmationState(for: session)
            session.setValue(resumedAt, forKey: "lastObservedAt")
            if let snapshot {
                session.setValue(snapshot.currentAmps, forKey: "lastObservedCurrentAmps")
                session.setValue(snapshot.powerWatts, forKey: "lastObservedPowerWatts")
                session.setValue(
                    chargingTransportMode(for: session) == .wired ? snapshot.voltageVolts : nil,
                    forKey: "lastObservedVoltageVolts"
                )
            } else {
                session.setValue(0, forKey: "lastObservedCurrentAmps")
                session.setValue(0, forKey: "lastObservedPowerWatts")
                session.setValue(nil, forKey: "lastObservedVoltageVolts")
            }
            session.setValue(resumedAt, forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func stopSession(
        id sessionID: UUID,
        finalBatteryPercent: Double? = nil
    ) -> Bool {
        if let finalBatteryPercent {
            guard finalBatteryPercent.isFinite, finalBatteryPercent >= 0, finalBatteryPercent <= 100 else {
                return false
            }
        }

        var didSave = false
        var deviceIDToRefresh: String?

        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            guard statusValue(session, key: "statusRawValue")?.isOpen == true else {
                return
            }

            guard hasSavableChargeData(session) else {
                return
            }

            let observedAt = snapshotDateForManualStop(session)
            finishSession(
                session,
                observedAt: observedAt,
                finalBatteryPercent: finalBatteryPercent,
                status: .completed
            )

            guard saveContext() else {
                return
            }

            didSave = true
            deviceIDToRefresh = stringValue(session, key: "chargedDeviceID")
        }

        if let deviceID = deviceIDToRefresh {
            context.perform { [weak self] in
                guard let self else { return }
                self.refreshDerivedMetrics(forChargedDeviceID: deviceID)
                self.saveContext()
            }
        }

        return didSave
    }

    @discardableResult
    func addBatteryCheckpoint(
        percent: Double,
        for meterMACAddress: String,
        measuredEnergyWh: Double? = nil,
        measuredChargeAh: Double? = nil
    ) -> Bool {
        guard percent.isFinite, percent >= 0, percent <= 100 else {
            return false
        }

        var didSave = false
        context.performAndWait {
            guard let session = fetchOpenSessionObject(forMeterMACAddress: meterMACAddress) else {
                return
            }

            didSave = addBatteryCheckpoint(
                percent: percent,
                measuredEnergyWh: measuredEnergyWh,
                measuredChargeAh: measuredChargeAh,
                flag: .intermediate,
                to: session
            )
        }
        return didSave
    }

    @discardableResult
    func addBatteryCheckpoint(
        percent: Double,
        for sessionID: UUID,
        measuredEnergyWh: Double? = nil,
        measuredChargeAh: Double? = nil
    ) -> Bool {
        guard percent.isFinite, percent >= 0, percent <= 100 else {
            return false
        }

        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            didSave = addBatteryCheckpoint(
                percent: percent,
                measuredEnergyWh: measuredEnergyWh,
                measuredChargeAh: measuredChargeAh,
                flag: .intermediate,
                to: session
            )
        }
        return didSave
    }

    @discardableResult
    func deleteBatteryCheckpoint(
        id checkpointID: UUID,
        from sessionID: UUID
    ) -> Bool {
        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString),
                  let checkpoint = fetchCheckpointObject(
                    id: checkpointID.uuidString,
                    sessionID: sessionID.uuidString
                  ) else {
                return
            }

            let chargedDeviceID = stringValue(session, key: "chargedDeviceID")
            context.delete(checkpoint)
            refreshCheckpointDerivedValues(for: session)

            if let chargedDeviceID {
                refreshDerivedMetrics(forChargedDeviceID: chargedDeviceID)
            }

            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func setTargetBatteryPercent(_ percent: Double?, for sessionID: UUID) -> Bool {
        if let percent, (!percent.isFinite || percent <= 0 || percent > 100) {
            return false
        }

        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            session.setValue(percent, forKey: "targetBatteryPercent")
            session.setValue(nil, forKey: "targetBatteryAlertTriggeredAt")
            session.setValue(Date(), forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func confirmCompletion(for sessionID: UUID) -> Bool {
        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            guard statusValue(session, key: "statusRawValue") == .active else {
                return
            }

            finishSession(
                session,
                observedAt: dateValue(session, key: "lastObservedAt") ?? Date(),
                finalBatteryPercent: nil,
                status: .completed
            )

            if saveContext() {
                if let deviceID = stringValue(session, key: "chargedDeviceID") {
                    refreshDerivedMetrics(forChargedDeviceID: deviceID)
                    didSave = saveContext()
                } else {
                    didSave = true
                }
            }
        }
        return didSave
    }

    @discardableResult
    func continueMonitoringDespiteCompletionContradiction(for sessionID: UUID) -> Bool {
        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            guard statusValue(session, key: "statusRawValue") == .active else {
                return
            }

            clearCompletionConfirmationState(for: session)
            session.setValue(nil, forKey: "belowThresholdSince")
            session.setValue(Date().addingTimeInterval(completionConfirmationCooldown), forKey: "completionConfirmationCooldownUntil")
            session.setValue(Date(), forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func setSessionTrim(sessionID: UUID, start: Date?, end: Date?) -> Bool {
        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            let sessionStart = dateValue(session, key: "startedAt") ?? Date.distantPast
            let sessionEnd   = dateValue(session, key: "endedAt")
                ?? dateValue(session, key: "lastObservedAt")
                ?? Date.distantFuture

            let effectiveStart = min(max(start ?? sessionStart, sessionStart), sessionEnd)
            let effectiveEnd   = max(min(end ?? sessionEnd, sessionEnd), effectiveStart)
            let persistedStart = effectiveStart == sessionStart ? nil : effectiveStart
            let persistedEnd   = effectiveEnd == sessionEnd ? nil : effectiveEnd

            let allSamples = fetchSessionSampleObjects(forSessionID: sessionID.uuidString)
                .compactMap { obj -> (timestamp: Date, energy: Double, charge: Double)? in
                    guard let ts = dateValue(obj, key: "timestamp") else { return nil }
                    return (
                        timestamp: ts,
                        energy: doubleValue(obj, key: "measuredEnergyWh"),
                        charge: doubleValue(obj, key: "measuredChargeAh")
                    )
                }
                .sorted { $0.timestamp < $1.timestamp }

            // Each sample stores cumulative energy since session start.
            // Trimmed energy = value at trimEnd  -  value just before trimStart.
            let baselineSample = allSamples.last { $0.timestamp <= effectiveStart }
            let endSample      = allSamples.last { $0.timestamp <= effectiveEnd }
            let baselineEnergy = baselineSample?.energy ?? 0
            let baselineCharge = baselineSample?.charge ?? 0

            if let endSample {
                let trimmedEnergy  = max(endSample.energy - baselineEnergy, 0)
                let trimmedCharge  = max(endSample.charge - baselineCharge, 0)
                session.setValue(trimmedEnergy, forKey: "measuredEnergyWh")
                session.setValue(trimmedCharge, forKey: "measuredChargeAh")
            } else {
                session.setValue(0, forKey: "measuredEnergyWh")
                session.setValue(0, forKey: "measuredChargeAh")
            }

            session.setValue(persistedStart, forKey: "trimStart")
            session.setValue(persistedEnd,   forKey: "trimEnd")
            session.setValue(Date(), forKey: "updatedAt")

            let checkpoints = fetchCheckpointObjects(forSessionID: sessionID.uuidString)
            for checkpoint in checkpoints {
                guard let timestamp = dateValue(checkpoint, key: "timestamp") else { continue }

                if timestamp < effectiveStart || timestamp > effectiveEnd {
                    context.delete(checkpoint)
                    continue
                }

                let checkpointSample = allSamples.last { $0.timestamp <= timestamp }
                let rebasedEnergy = max((checkpointSample?.energy ?? baselineEnergy) - baselineEnergy, 0)
                let rebasedCharge = max((checkpointSample?.charge ?? baselineCharge) - baselineCharge, 0)
                checkpoint.setValue(rebasedEnergy, forKey: "measuredEnergyWh")
                checkpoint.setValue(rebasedCharge, forKey: "measuredChargeAh")
            }

            let remainingCheckpoints = fetchCheckpointObjects(forSessionID: sessionID.uuidString)
                .sorted {
                    (dateValue($0, key: "timestamp") ?? .distantPast)
                        < (dateValue($1, key: "timestamp") ?? .distantPast)
                }
            let restoredInitialCheckpoint = remainingCheckpoints.first { checkpoint in
                let label = stringValue(checkpoint, key: "label")
                let timestamp = dateValue(checkpoint, key: "timestamp") ?? .distantFuture
                return ChargeCheckpointFlag.fromStoredLabel(label) == .initial || timestamp <= effectiveStart
            }

            if persistedStart == nil {
                if let restoredInitialCheckpoint,
                   let percent = optionalDoubleValue(restoredInitialCheckpoint, key: "batteryPercent"),
                   percent >= 0 {
                    session.setValue(percent, forKey: "startBatteryPercent")
                }
            } else {
                session.setValue(nil, forKey: "startBatteryPercent")
            }

            refreshCheckpointDerivedValues(for: session)

            if let chargedDeviceID = stringValue(session, key: "chargedDeviceID") {
                refreshDerivedMetrics(forChargedDeviceID: chargedDeviceID)
            }

            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func deleteChargeSession(id sessionID: UUID) -> Bool {
        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString) else {
                return
            }

            let chargedDeviceID = stringValue(session, key: "chargedDeviceID")

            fetchCheckpointObjects(forSessionID: sessionID.uuidString).forEach(context.delete)
            fetchSessionSampleObjects(forSessionID: sessionID.uuidString).forEach(context.delete)
            context.delete(session)

            guard saveContext() else {
                return
            }

            if let chargedDeviceID {
                refreshDerivedMetrics(forChargedDeviceID: chargedDeviceID)
                didSave = saveContext()
            } else {
                didSave = true
            }
        }
        return didSave
    }

    @discardableResult
    func deleteChargedDevice(id chargedDeviceID: UUID) -> Bool {
        var didSave = false

        context.performAndWait {
            guard let chargedDevice = fetchChargedDeviceObject(id: chargedDeviceID.uuidString) else {
                return
            }

            let deviceClass = ChargedDeviceClass(rawValue: stringValue(chargedDevice, key: "deviceClassRawValue") ?? "")
            let deviceSessions = fetchSessions(forChargedDeviceID: chargedDeviceID.uuidString)
            let linkedWirelessSessions = fetchSessions(forChargerID: chargedDeviceID.uuidString)

            var impactedChargedDeviceIDs = Set<String>()

            for session in deviceSessions {
                if let impactedID = stringValue(session, key: "chargedDeviceID") {
                    impactedChargedDeviceIDs.insert(impactedID)
                }
                if let impactedChargerID = stringValue(session, key: "chargerID") {
                    impactedChargedDeviceIDs.insert(impactedChargerID)
                }
                if let sessionID = stringValue(session, key: "id") {
                    fetchCheckpointObjects(forSessionID: sessionID).forEach(context.delete)
                    fetchSessionSampleObjects(forSessionID: sessionID).forEach(context.delete)
                }
                context.delete(session)
            }

            if deviceClass == .charger {
                for session in linkedWirelessSessions {
                    guard stringValue(session, key: "chargedDeviceID") != chargedDeviceID.uuidString else {
                        continue
                    }
                    if let impactedID = stringValue(session, key: "chargedDeviceID") {
                        impactedChargedDeviceIDs.insert(impactedID)
                    }
                    session.setValue(nil, forKey: "chargerID")
                    session.setValue(Date(), forKey: "updatedAt")
                }
            }

            context.delete(chargedDevice)

            guard saveContext() else {
                return
            }

            impactedChargedDeviceIDs.remove(chargedDeviceID.uuidString)
            for impactedID in impactedChargedDeviceIDs {
                refreshDerivedMetrics(forChargedDeviceID: impactedID)
            }
            didSave = saveContext()
        }

        return didSave
    }

    @discardableResult
    func observe(snapshot: ChargingMonitorSnapshot) -> Bool {
        var didSave = false

        context.performAndWait {
            guard let session = fetchOpenSessionObject(forMeterMACAddress: snapshot.meterMACAddress),
                  let resolvedDevice = stringValue(session, key: "chargedDeviceID").flatMap(fetchChargedDeviceObject(id:)) else {
                return
            }

            if statusValue(session, key: "statusRawValue") == .paused {
                if maybeCompleteOpenSession(session, observedAt: snapshot.observedAt) {
                    didSave = true
                }
                return
            }

            let chargingTransportMode = self.chargingTransportMode(for: session)
            let chargingStateMode = self.chargingStateMode(for: session)
            let charger = chargingTransportMode == .wireless
                ? stringValue(session, key: "chargerID").flatMap(fetchChargedDeviceObject(id:))
                : nil
            guard chargingTransportMode == .wired || charger != nil else {
                return
            }
            let stopThreshold = resolvedStopThreshold(
                for: resolvedDevice,
                chargingTransportMode: chargingTransportMode,
                chargingStateMode: chargingStateMode,
                charger: charger,
                fallback: optionalDoubleValue(session, key: "stopThresholdAmps")
            )

            let sessionSnapshot = snapshotClampedToMaximumDuration(snapshot, for: session)
            update(session: session, with: sessionSnapshot, stopThreshold: stopThreshold, charger: charger)
            let aggregatedSample = updateAggregatedSample(session: session, with: sessionSnapshot)
            if let completionDate = automaticCompletionDate(for: session, referenceDate: snapshot.observedAt),
               statusValue(session, key: "statusRawValue")?.isOpen == true {
                finishSession(
                    session,
                    observedAt: completionDate,
                    finalBatteryPercent: nil,
                    status: .completed
                )
            }

            let saveReason = saveReason(for: session, observedAt: sessionSnapshot.observedAt)
            let shouldPersistAggregatedCurve = aggregatedSample.map {
                shouldPersistAggregatedSample($0, observedAt: sessionSnapshot.observedAt)
            } ?? false

            guard saveReason != .none || shouldPersistAggregatedCurve else {
                return
            }

            session.setValue(sessionSnapshot.observedAt, forKey: "updatedAt")

            if saveContext() {
                if saveReason == .completed, let deviceID = stringValue(session, key: "chargedDeviceID") {
                    refreshDerivedMetrics(forChargedDeviceID: deviceID)
                    didSave = saveContext()
                } else {
                    didSave = true
                }
            }
        }

        return didSave
    }

    func fetchChargedDeviceSummaries() -> [ChargedDeviceSummary] {
        var summaries: [ChargedDeviceSummary] = []

        context.performAndWait {
            let devices = fetchObjects(entityName: EntityName.chargedDevice)
            let sessions = fetchObjects(entityName: EntityName.chargeSession)
            let checkpoints = fetchObjects(entityName: EntityName.chargeCheckpoint)

            let checkpointsBySessionID = Dictionary(grouping: checkpoints) { stringValue($0, key: "sessionID") ?? "" }
            let sessionsByDeviceID = Dictionary(grouping: sessions) { stringValue($0, key: "chargedDeviceID") ?? "" }
            let sessionsByChargerID = Dictionary(grouping: sessions) { stringValue($0, key: "chargerID") ?? "" }
            let sampleBackedSessionIDs = sampleBackedSessionIDs(
                devices: devices,
                sessionsByDeviceID: sessionsByDeviceID,
                sessionsByChargerID: sessionsByChargerID
            )
            let samplesBySessionID = Dictionary(
                grouping: fetchSessionSampleObjects(forSessionIDs: Array(sampleBackedSessionIDs))
            ) { stringValue($0, key: "sessionID") ?? "" }

            summaries = devices.compactMap { device in
                guard
                    let id = uuidValue(device, key: "id"),
                    let name = stringValue(device, key: "name"),
                    let qrIdentifier = stringValue(device, key: "qrIdentifier"),
                    let rawClass = stringValue(device, key: "deviceClassRawValue"),
                    let deviceClass = ChargedDeviceClass(rawValue: rawClass)
                else {
                    return nil
                }

                let chargingStateAvailability = chargingStateAvailability(for: device)
                let supportsWiredCharging = supportsWiredCharging(for: device)
                let supportsWirelessCharging = supportsWirelessCharging(for: device)
                let templateDefinition = templateDefinition(for: device)

                let sessionObjects = relevantSessionObjects(
                    for: id.uuidString,
                    deviceClass: deviceClass,
                    sessionsByDeviceID: sessionsByDeviceID,
                    sessionsByChargerID: sessionsByChargerID
                )
                let sessionSummaries = sessionObjects
                    .compactMap { session in
                        makeSessionSummary(
                            from: session,
                            checkpoints: checkpointsBySessionID[stringValue(session, key: "id") ?? ""] ?? [],
                            samples: samplesBySessionID[stringValue(session, key: "id") ?? ""] ?? []
                        )
                    }
                    .sorted { lhs, rhs in
                        if lhs.status.isOpen && !rhs.status.isOpen {
                            return true
                        }
                        if !lhs.status.isOpen && rhs.status.isOpen {
                            return false
                        }
                        if lhs.status == .active && rhs.status == .paused {
                            return true
                        }
                        if lhs.status == .paused && rhs.status == .active {
                            return false
                        }
                        return lhs.startedAt > rhs.startedAt
                    }

                return ChargedDeviceSummary(
                    id: id,
                    qrIdentifier: qrIdentifier,
                    name: name,
                    deviceClass: deviceClass,
                    deviceTemplateID: stringValue(device, key: "deviceTemplateID"),
                    templateDefinition: templateDefinition,
                    supportsChargingWhileOff: chargingStateAvailability.supportsChargingWhileOff,
                    chargingStateAvailability: chargingStateAvailability,
                    supportsWiredCharging: supportsWiredCharging,
                    supportsWirelessCharging: supportsWirelessCharging,
                    chargerType: chargerType(for: device),
                    wirelessChargingProfile: wirelessChargingProfile(for: device),
                    configuredCompletionCurrents: decodedCompletionCurrents(from: device, key: "configuredCompletionCurrentsRawValue"),
                    learnedCompletionCurrents: decodedCompletionCurrents(from: device, key: "learnedCompletionCurrentsRawValue"),
                    wirelessChargerEfficiencyFactor: optionalDoubleValue(device, key: "wirelessChargerEfficiencyFactor"),
                    wiredChargeCompletionCurrentAmps: optionalDoubleValue(device, key: "wiredChargeCompletionCurrentAmps"),
                    wirelessChargeCompletionCurrentAmps: optionalDoubleValue(device, key: "wirelessChargeCompletionCurrentAmps"),
                    chargerObservedVoltageSelections: decodedObservedVoltageSelections(from: device),
                    chargerIdleCurrentAmps: optionalDoubleValue(device, key: "chargerIdleCurrentAmps"),
                    chargerEfficiencyFactor: optionalDoubleValue(device, key: "chargerEfficiencyFactor"),
                    chargerMaximumPowerWatts: optionalDoubleValue(device, key: "chargerMaximumPowerWatts"),
                    notes: stringValue(device, key: "notes"),
                    minimumCurrentAmps: optionalDoubleValue(device, key: "minimumCurrentAmps"),
                    estimatedBatteryCapacityWh: optionalDoubleValue(device, key: "estimatedBatteryCapacityWh"),
                    wiredMinimumCurrentAmps: optionalDoubleValue(device, key: "wiredMinimumCurrentAmps"),
                    wirelessMinimumCurrentAmps: optionalDoubleValue(device, key: "wirelessMinimumCurrentAmps"),
                    wiredEstimatedBatteryCapacityWh: optionalDoubleValue(device, key: "wiredEstimatedBatteryCapacityWh"),
                    wirelessEstimatedBatteryCapacityWh: optionalDoubleValue(device, key: "wirelessEstimatedBatteryCapacityWh"),
                    lastAssociatedMeterMAC: stringValue(device, key: "lastAssociatedMeterMAC"),
                    createdAt: dateValue(device, key: "createdAt") ?? .distantPast,
                    updatedAt: dateValue(device, key: "updatedAt") ?? .distantPast,
                    sessions: sessionSummaries,
                    capacityHistory: buildCapacityHistory(from: sessionSummaries),
                    typicalCurve: buildTypicalCurve(from: sessionSummaries),
                    standbyPowerMeasurements: []
                )
            }
            .sorted { lhs, rhs in
                if lhs.activeSession != nil && rhs.activeSession == nil {
                    return true
                }
                if lhs.activeSession == nil && rhs.activeSession != nil {
                    return false
                }
                if lhs.updatedAt != rhs.updatedAt {
                    return lhs.updatedAt > rhs.updatedAt
                }
                return lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending
            }
        }

        return summaries
    }

    func resolvedChargedDeviceSummary(forMeterMACAddress meterMACAddress: String) -> ChargedDeviceSummary? {
        let normalizedMAC = normalizedMACAddress(meterMACAddress)
        guard !normalizedMAC.isEmpty else { return nil }

        let summaries = fetchChargedDeviceSummaries().filter { !$0.isCharger }

        if let activeMatch = summaries.first(where: { summary in
            summary.activeSession?.meterMACAddress == normalizedMAC
        }) {
            return activeMatch
        }

        return summaries.first(where: { $0.lastAssociatedMeterMAC == normalizedMAC })
    }

    func activeChargeSessionSummary(forMeterMACAddress meterMACAddress: String) -> ChargeSessionSummary? {
        let normalizedMAC = normalizedMACAddress(meterMACAddress)
        guard !normalizedMAC.isEmpty else { return nil }

        var summary: ChargeSessionSummary?

        context.performAndWait {
            guard let session = fetchOpenSessionObject(forMeterMACAddress: normalizedMAC),
                  let sessionID = stringValue(session, key: "id") else {
                return
            }

            summary = makeSessionSummary(
                from: session,
                checkpoints: fetchCheckpointObjects(forSessionID: sessionID),
                samples: fetchSessionSampleObjects(forSessionID: sessionID)
            )
        }

        return summary
    }

    private func createSessionObject(
        for chargedDevice: NSManagedObject,
        charger: NSManagedObject?,
        snapshot: ChargingMonitorSnapshot,
        stopThreshold: Double?,
        chargingTransportMode: ChargingTransportMode,
        chargingStateMode: ChargingStateMode,
        autoStopEnabled: Bool
    ) -> NSManagedObject? {
        guard
            let entity = NSEntityDescription.entity(forEntityName: EntityName.chargeSession, in: context),
            let chargedDeviceID = stringValue(chargedDevice, key: "id")
        else {
            return nil
        }

        let session = NSManagedObject(entity: entity, insertInto: context)
        let now = snapshot.observedAt
        session.setValue(UUID().uuidString, forKey: "id")
        session.setValue(chargedDeviceID, forKey: "chargedDeviceID")
        session.setValue(charger.flatMap { stringValue($0, key: "id") }, forKey: "chargerID")
        session.setValue(snapshot.meterMACAddress, forKey: "meterMACAddress")
        session.setValue(snapshot.meterName, forKey: "meterName")
        session.setValue(snapshot.meterModel, forKey: "meterModel")
        session.setValue(now, forKey: "startedAt")
        session.setValue(now, forKey: "lastObservedAt")
        session.setValue(ChargeSessionStatus.active.rawValue, forKey: "statusRawValue")
        let usesMeterCounters = snapshot.meterEnergyCounterWh != nil || snapshot.meterChargeCounterAh != nil
        session.setValue(
            (usesMeterCounters ? ChargeSessionSourceMode.offline : .live).rawValue,
            forKey: "sourceModeRawValue"
        )
        session.setValue(chargingTransportMode.rawValue, forKey: "chargingTransportRawValue")
        session.setValue(chargingStateMode.rawValue, forKey: "chargingStateRawValue")
        session.setValue(autoStopEnabled, forKey: "autoStopEnabled")
        session.setValue(stopThreshold ?? 0, forKey: "stopThresholdAmps")
        session.setValue(snapshot.voltageVolts, forKey: "selectedSourceVoltageVolts")
        session.setValue(snapshot.currentAmps, forKey: "lastObservedCurrentAmps")
        session.setValue(snapshot.powerWatts, forKey: "lastObservedPowerWatts")
        session.setValue(
            chargingTransportMode == .wired ? snapshot.voltageVolts : nil,
            forKey: "lastObservedVoltageVolts"
        )
        session.setValue(
            hasObservedChargeFlow(
                currentAmps: snapshot.currentAmps,
                chargingTransportMode: chargingTransportMode,
                charger: charger,
                stopThreshold: stopThreshold
            ),
            forKey: "hasObservedChargeFlow"
        )
        session.setValue(snapshot.currentAmps, forKey: "minimumObservedCurrentAmps")
        session.setValue(snapshot.currentAmps, forKey: "maximumObservedCurrentAmps")
        session.setValue(snapshot.powerWatts, forKey: "maximumObservedPowerWatts")
        session.setValue(
            chargingTransportMode == .wired ? snapshot.voltageVolts : nil,
            forKey: "maximumObservedVoltageVolts"
        )
        session.setValue(boolValue(chargedDevice, key: "supportsChargingWhileOff"), forKey: "supportsChargingWhileOff")
        if let selectedDataGroup = snapshot.selectedDataGroup {
            session.setValue(Int16(selectedDataGroup), forKey: "selectedDataGroup")
        }
        if let meterEnergyCounterWh = snapshot.meterEnergyCounterWh {
            session.setValue(meterEnergyCounterWh, forKey: "meterEnergyBaselineWh")
            session.setValue(meterEnergyCounterWh, forKey: "meterLastEnergyWh")
        }
        if let meterChargeCounterAh = snapshot.meterChargeCounterAh {
            session.setValue(meterChargeCounterAh, forKey: "meterChargeBaselineAh")
            session.setValue(meterChargeCounterAh, forKey: "meterLastChargeAh")
        }
        if let meterRecordingDurationSeconds = snapshot.meterRecordingDurationSeconds {
            setValue(meterRecordingDurationSeconds, on: session, key: "meterDurationBaselineSeconds")
            setValue(meterRecordingDurationSeconds, on: session, key: "meterLastDurationSeconds")
        }
        session.setValue(now, forKey: "createdAt")
        session.setValue(now, forKey: "updatedAt")

        chargedDevice.setValue(snapshot.meterMACAddress, forKey: "lastAssociatedMeterMAC")
        chargedDevice.setValue(now, forKey: "updatedAt")
        return session
    }

    private func update(
        session: NSManagedObject,
        with snapshot: ChargingMonitorSnapshot,
        stopThreshold: Double?,
        charger: NSManagedObject?
    ) {
        let sessionChargingTransportMode = chargingTransportMode(for: session)
        let lastObservedAt = dateValue(session, key: "lastObservedAt")
        let previousPower = doubleValue(session, key: "lastObservedPowerWatts")
        let previousCurrent = doubleValue(session, key: "lastObservedCurrentAmps")
        var measuredEnergyWh = doubleValue(session, key: "measuredEnergyWh")
        var measuredChargeAh = doubleValue(session, key: "measuredChargeAh")
        var sourceMode = ChargeSessionSourceMode(rawValue: stringValue(session, key: "sourceModeRawValue") ?? "") ?? .live
        var usedOfflineMeterCounters = boolValue(session, key: "usedOfflineMeterCounters")

        if let lastObservedAt {
            let deltaSeconds = max(snapshot.observedAt.timeIntervalSince(lastObservedAt), 0)
            if deltaSeconds > 0, deltaSeconds <= maximumLiveIntegrationGap {
                measuredEnergyWh += max(previousPower, 0) * deltaSeconds / 3600
                measuredChargeAh += max(previousCurrent, 0) * deltaSeconds / 3600
                if sourceMode == .offline {
                    sourceMode = .blended
                }
            }
        }

        if let counterGroup = snapshot.selectedDataGroup,
           let storedGroup = optionalInt16Value(session, key: "selectedDataGroup"),
           UInt8(storedGroup) != counterGroup {
            session.setValue(Int16(counterGroup), forKey: "selectedDataGroup")
            session.setValue(snapshot.meterEnergyCounterWh, forKey: "meterEnergyBaselineWh")
            session.setValue(snapshot.meterChargeCounterAh, forKey: "meterChargeBaselineAh")
        }

        if let meterEnergyCounterWh = snapshot.meterEnergyCounterWh {
            let baselineEnergy = optionalDoubleValue(session, key: "meterEnergyBaselineWh") ?? meterEnergyCounterWh
            let lastEnergy = optionalDoubleValue(session, key: "meterLastEnergyWh")
            if optionalDoubleValue(session, key: "meterEnergyBaselineWh") == nil {
                session.setValue(baselineEnergy, forKey: "meterEnergyBaselineWh")
            }

            if meterEnergyCounterWh + counterDecreaseTolerance >= baselineEnergy {
                let offlineEnergy = meterEnergyCounterWh - baselineEnergy
                measuredEnergyWh = max(offlineEnergy, 0)
                usedOfflineMeterCounters = true
                sourceMode = .offline
            } else if let lastEnergy, meterEnergyCounterWh > lastEnergy {
                let delta = meterEnergyCounterWh - lastEnergy
                if delta > 0 {
                    measuredEnergyWh += delta
                    usedOfflineMeterCounters = true
                    sourceMode = .blended
                }
            }
            session.setValue(meterEnergyCounterWh, forKey: "meterLastEnergyWh")
        }

        if let meterChargeCounterAh = snapshot.meterChargeCounterAh {
            let baselineCharge = optionalDoubleValue(session, key: "meterChargeBaselineAh") ?? meterChargeCounterAh
            let lastCharge = optionalDoubleValue(session, key: "meterLastChargeAh")
            if optionalDoubleValue(session, key: "meterChargeBaselineAh") == nil {
                session.setValue(baselineCharge, forKey: "meterChargeBaselineAh")
            }

            if meterChargeCounterAh + counterDecreaseTolerance >= baselineCharge {
                let offlineCharge = meterChargeCounterAh - baselineCharge
                measuredChargeAh = max(offlineCharge, 0)
                usedOfflineMeterCounters = true
            } else if let lastCharge, meterChargeCounterAh > lastCharge {
                let delta = meterChargeCounterAh - lastCharge
                if delta > 0 {
                    measuredChargeAh += delta
                    usedOfflineMeterCounters = true
                }
            }
            session.setValue(meterChargeCounterAh, forKey: "meterLastChargeAh")
        }

        if let meterRecordingDurationSeconds = snapshot.meterRecordingDurationSeconds {
            let baselineDuration = optionalDoubleValue(session, key: "meterDurationBaselineSeconds") ?? meterRecordingDurationSeconds
            if optionalDoubleValue(session, key: "meterDurationBaselineSeconds") == nil {
                setValue(baselineDuration, on: session, key: "meterDurationBaselineSeconds")
            }
            setValue(meterRecordingDurationSeconds, on: session, key: "meterLastDurationSeconds")
        }

        let existingMinimum = optionalDoubleValue(session, key: "minimumObservedCurrentAmps")
        let updatedMinimum: Double
        if snapshot.currentAmps > 0 {
            updatedMinimum = min(existingMinimum ?? snapshot.currentAmps, snapshot.currentAmps)
        } else {
            updatedMinimum = existingMinimum ?? 0
        }

        let effectiveCurrent = effectiveCurrentAmps(
            fromMeasuredCurrent: snapshot.currentAmps,
            chargingTransportMode: sessionChargingTransportMode,
            charger: charger
        )
        let observedChargeFlow = boolValue(session, key: "hasObservedChargeFlow")
            || hasObservedChargeFlow(
                currentAmps: snapshot.currentAmps,
                chargingTransportMode: sessionChargingTransportMode,
                charger: charger,
                stopThreshold: stopThreshold
            )

        session.setValue(measuredEnergyWh, forKey: "measuredEnergyWh")
        session.setValue(measuredChargeAh, forKey: "measuredChargeAh")
        session.setValue(updatedMinimum, forKey: "minimumObservedCurrentAmps")
        session.setValue(stopThreshold ?? 0, forKey: "stopThresholdAmps")
        session.setValue(snapshot.observedAt, forKey: "lastObservedAt")
        session.setValue(snapshot.currentAmps, forKey: "lastObservedCurrentAmps")
        session.setValue(snapshot.powerWatts, forKey: "lastObservedPowerWatts")
        session.setValue(
            sessionChargingTransportMode == .wired ? snapshot.voltageVolts : nil,
            forKey: "lastObservedVoltageVolts"
        )
        session.setValue(observedChargeFlow, forKey: "hasObservedChargeFlow")
        session.setValue(
            max(optionalDoubleValue(session, key: "maximumObservedCurrentAmps") ?? snapshot.currentAmps, snapshot.currentAmps),
            forKey: "maximumObservedCurrentAmps"
        )
        session.setValue(
            max(optionalDoubleValue(session, key: "maximumObservedPowerWatts") ?? snapshot.powerWatts, snapshot.powerWatts),
            forKey: "maximumObservedPowerWatts"
        )
        session.setValue(
            sessionChargingTransportMode == .wired
                ? max(optionalDoubleValue(session, key: "maximumObservedVoltageVolts") ?? snapshot.voltageVolts, snapshot.voltageVolts)
                : nil,
            forKey: "maximumObservedVoltageVolts"
        )
        session.setValue(usedOfflineMeterCounters, forKey: "usedOfflineMeterCounters")
        session.setValue(sourceMode.rawValue, forKey: "sourceModeRawValue")
        maybeTriggerTargetBatteryAlert(for: session, observedAt: snapshot.observedAt)

        guard boolValue(session, key: "autoStopEnabled"), let stopThreshold, stopThreshold > 0, observedChargeFlow else {
            session.setValue(nil, forKey: "belowThresholdSince")
            clearCompletionConfirmationState(for: session)
            session.setValue(nil, forKey: "completionConfirmationCooldownUntil")
            return
        }

        if effectiveCurrent <= stopThreshold {
            let belowThresholdSince = dateValue(session, key: "belowThresholdSince") ?? snapshot.observedAt
            session.setValue(belowThresholdSince, forKey: "belowThresholdSince")
            if snapshot.observedAt.timeIntervalSince(belowThresholdSince) >= stopDetectionHoldDuration {
                if boolValue(session, key: "requiresCompletionConfirmation") {
                    // Leave the session active until the user explicitly confirms or charging resumes.
                    return
                }

                if shouldRequireCompletionConfirmation(for: session, observedAt: snapshot.observedAt) {
                    requestCompletionConfirmation(for: session, observedAt: snapshot.observedAt)
                } else {
                    finishSession(
                        session,
                        observedAt: snapshot.observedAt,
                        finalBatteryPercent: nil,
                        status: .completed
                    )
                }
            }
        } else {
            session.setValue(nil, forKey: "belowThresholdSince")
            clearCompletionConfirmationState(for: session)
            session.setValue(nil, forKey: "completionConfirmationCooldownUntil")
        }
    }

    private func updateAggregatedSample(
        session: NSManagedObject,
        with snapshot: ChargingMonitorSnapshot
    ) -> NSManagedObject? {
        guard
            let sessionID = stringValue(session, key: "id"),
            let chargedDeviceID = stringValue(session, key: "chargedDeviceID"),
            let startedAt = dateValue(session, key: "startedAt"),
            let entity = NSEntityDescription.entity(forEntityName: EntityName.chargeSessionSample, in: context)
        else {
            return nil
        }

        let elapsed = max(snapshot.observedAt.timeIntervalSince(startedAt), 0)
        let bucketIndex = Int32(floor(elapsed / Self.aggregatedSampleBucketDuration))
        let bucketStart = startedAt.addingTimeInterval(Double(bucketIndex) * Self.aggregatedSampleBucketDuration)
        let bucketIdentifier = "\(sessionID)-\(bucketIndex)"
        let sample = fetchSessionSampleObject(sessionID: sessionID, bucketIndex: bucketIndex)
            ?? NSManagedObject(entity: entity, insertInto: context)
        let sessionChargingTransportMode = chargingTransportMode(for: session)
        let sampleVoltage = sessionChargingTransportMode == .wired ? snapshot.voltageVolts : nil

        let existingCount = max(optionalInt16Value(sample, key: "sampleCount") ?? 0, 0)
        let updatedCount = existingCount + 1

        sample.setValue(bucketIdentifier, forKey: "id")
        sample.setValue(sessionID, forKey: "sessionID")
        sample.setValue(chargedDeviceID, forKey: "chargedDeviceID")
        sample.setValue(bucketIndex, forKey: "bucketIndex")
        sample.setValue(max(snapshot.observedAt, bucketStart), forKey: "timestamp")
        sample.setValue(
            runningAverage(
                currentAverage: optionalDoubleValue(sample, key: "averageCurrentAmps") ?? snapshot.currentAmps,
                currentCount: Int(existingCount),
                newValue: snapshot.currentAmps
            ),
            forKey: "averageCurrentAmps"
        )
        sample.setValue(
            sampleVoltage.flatMap { voltage in
                runningAverage(
                    currentAverage: optionalDoubleValue(sample, key: "averageVoltageVolts") ?? voltage,
                    currentCount: Int(existingCount),
                    newValue: voltage
                )
            },
            forKey: "averageVoltageVolts"
        )
        sample.setValue(
            runningAverage(
                currentAverage: optionalDoubleValue(sample, key: "averagePowerWatts") ?? snapshot.powerWatts,
                currentCount: Int(existingCount),
                newValue: snapshot.powerWatts
            ),
            forKey: "averagePowerWatts"
        )
        sample.setValue(doubleValue(session, key: "measuredEnergyWh"), forKey: "measuredEnergyWh")
        sample.setValue(doubleValue(session, key: "measuredChargeAh"), forKey: "measuredChargeAh")
        sample.setValue(Int16(updatedCount), forKey: "sampleCount")
        sample.setValue(dateValue(sample, key: "createdAt") ?? snapshot.observedAt, forKey: "createdAt")
        sample.setValue(snapshot.observedAt, forKey: "updatedAt")
        return sample
    }

    private func maybeTriggerTargetBatteryAlert(
        for session: NSManagedObject,
        observedAt: Date,
        completionFallbackPercent: Double? = nil
    ) {
        guard dateValue(session, key: "targetBatteryAlertTriggeredAt") == nil else {
            return
        }

        guard let targetBatteryPercent = optionalDoubleValue(session, key: "targetBatteryPercent") else {
            return
        }

        let predictedBatteryPercent = predictedBatteryPercent(for: session)
            ?? optionalDoubleValue(session, key: "endBatteryPercent")
            ?? completionFallbackPercent

        guard let predictedBatteryPercent, predictedBatteryPercent >= targetBatteryPercent else {
            return
        }

        session.setValue(observedAt, forKey: "targetBatteryAlertTriggeredAt")
    }

    private func shouldRequireCompletionConfirmation(
        for session: NSManagedObject,
        observedAt: Date
    ) -> Bool {
        if let cooldownUntil = dateValue(session, key: "completionConfirmationCooldownUntil"),
           cooldownUntil > observedAt {
            return false
        }

        guard let predictedBatteryPercent = predictedBatteryPercent(for: session) else {
            return false
        }

        let expectedCompletionPercent = optionalDoubleValue(session, key: "targetBatteryPercent")
            ?? defaultCompletionPercentThreshold

        return predictedBatteryPercent + completionContradictionTolerancePercent < expectedCompletionPercent
    }

    private func requestCompletionConfirmation(for session: NSManagedObject, observedAt: Date) {
        guard !boolValue(session, key: "requiresCompletionConfirmation") else {
            return
        }

        session.setValue(true, forKey: "requiresCompletionConfirmation")
        session.setValue(observedAt, forKey: "completionConfirmationRequestedAt")
        session.setValue(predictedBatteryPercent(for: session), forKey: "completionContradictionPercent")
    }

    private func clearCompletionConfirmationState(for session: NSManagedObject) {
        session.setValue(false, forKey: "requiresCompletionConfirmation")
        session.setValue(nil, forKey: "completionConfirmationRequestedAt")
        session.setValue(nil, forKey: "completionContradictionPercent")
    }

    private func snapshotDateForManualStop(_ session: NSManagedObject) -> Date {
        if statusValue(session, key: "statusRawValue") == .paused {
            return dateValue(session, key: "pausedAt")
                ?? dateValue(session, key: "lastObservedAt")
                ?? Date()
        }
        return dateValue(session, key: "lastObservedAt") ?? Date()
    }

    private func snapshotClampedToMaximumDuration(
        _ snapshot: ChargingMonitorSnapshot,
        for session: NSManagedObject
    ) -> ChargingMonitorSnapshot {
        guard let maximumEndDate = maximumEndDate(for: session),
              snapshot.observedAt > maximumEndDate else {
            return snapshot
        }

        return ChargingMonitorSnapshot(
            meterMACAddress: snapshot.meterMACAddress,
            meterName: snapshot.meterName,
            meterModel: snapshot.meterModel,
            observedAt: maximumEndDate,
            voltageVolts: snapshot.voltageVolts,
            currentAmps: snapshot.currentAmps,
            powerWatts: snapshot.powerWatts,
            selectedDataGroup: snapshot.selectedDataGroup,
            meterChargeCounterAh: snapshot.meterChargeCounterAh,
            meterEnergyCounterWh: snapshot.meterEnergyCounterWh,
            meterRecordingDurationSeconds: snapshot.meterRecordingDurationSeconds,
            fallbackStopThresholdAmps: snapshot.fallbackStopThresholdAmps
        )
    }

    private func automaticCompletionDate(
        for session: NSManagedObject,
        referenceDate: Date
    ) -> Date? {
        guard statusValue(session, key: "statusRawValue")?.isOpen == true else {
            return nil
        }

        var completionDates: [Date] = []

        if let maximumEndDate = maximumEndDate(for: session) {
            completionDates.append(maximumEndDate)
        }

        if statusValue(session, key: "statusRawValue") == .paused,
           let pausedAt = dateValue(session, key: "pausedAt") {
            completionDates.append(pausedAt.addingTimeInterval(pausedSessionTimeout))
        }

        guard let completionDate = completionDates.min(),
              referenceDate >= completionDate else {
            return nil
        }

        return completionDate
    }

    private func maximumEndDate(for session: NSManagedObject) -> Date? {
        dateValue(session, key: "startedAt")?.addingTimeInterval(Self.maximumChargeSessionDuration)
    }

    @discardableResult
    private func maybeCompleteOpenSession(_ session: NSManagedObject, observedAt: Date) -> Bool {
        guard statusValue(session, key: "statusRawValue")?.isOpen == true,
              let completionDate = automaticCompletionDate(for: session, referenceDate: observedAt) else {
            return false
        }

        finishSession(
            session,
            observedAt: completionDate,
            finalBatteryPercent: nil,
            status: .completed
        )

        guard saveContext() else {
            return false
        }

        if let chargedDeviceID = stringValue(session, key: "chargedDeviceID") {
            refreshDerivedMetrics(forChargedDeviceID: chargedDeviceID)
            return saveContext()
        }

        return true
    }

    private func completionCurrentForSessionEnd(_ session: NSManagedObject) -> Double? {
        let chargingTransportMode = chargingTransportMode(for: session)
        let measuredCurrent = optionalDoubleValue(session, key: "lastObservedCurrentAmps")
            ?? doubleValue(session, key: "lastObservedCurrentAmps")

        guard measuredCurrent > 0 else {
            return nil
        }

        let charger = chargingTransportMode == .wireless
            ? stringValue(session, key: "chargerID").flatMap(fetchChargedDeviceObject(id:))
            : nil

        if chargingTransportMode == .wireless, chargerIdleCurrent(for: charger) == nil {
            return nil
        }

        let effectiveCurrent = effectiveCurrentAmps(
            fromMeasuredCurrent: measuredCurrent,
            chargingTransportMode: chargingTransportMode,
            charger: charger
        )
        guard effectiveCurrent > 0 else {
            return nil
        }
        return effectiveCurrent
    }

    private func finishSession(
        _ session: NSManagedObject,
        observedAt: Date,
        finalBatteryPercent: Double?,
        status: ChargeSessionStatus
    ) {
        if let finalBatteryPercent {
            _ = insertBatteryCheckpoint(
                percent: finalBatteryPercent,
                flag: .final,
                timestamp: observedAt,
                to: session
            )
        }

        session.setValue(status.rawValue, forKey: "statusRawValue")
        session.setValue(nil, forKey: "pausedAt")
        session.setValue(nil, forKey: "belowThresholdSince")
        session.setValue(observedAt, forKey: "endedAt")
        session.setValue(observedAt, forKey: "lastObservedAt")
        session.setValue(completionCurrentForSessionEnd(session), forKey: "completionCurrentAmps")
        clearCompletionConfirmationState(for: session)
        session.setValue(nil, forKey: "completionConfirmationCooldownUntil")
        updateCapacityEstimate(for: session)
        session.setValue(observedAt, forKey: "updatedAt")

        if status == .completed {
            maybeTriggerTargetBatteryAlert(
                for: session,
                observedAt: observedAt,
                completionFallbackPercent: defaultCompletionPercentThreshold
            )
        }
    }

    private func predictedBatteryPercent(for session: NSManagedObject) -> Double? {
        guard
            let chargedDeviceID = stringValue(session, key: "chargedDeviceID"),
            let chargedDevice = fetchChargedDeviceObject(id: chargedDeviceID),
            let estimatedCapacityWh = resolvedEstimatedBatteryCapacityWh(for: session, chargedDevice: chargedDevice),
            estimatedCapacityWh > 0
        else {
            return nil
        }

        // Compute effective battery energy dynamically so the prediction uses the
        // most current measuredEnergyWh rather than the stale effectiveBatteryEnergyWh
        // (which is only refreshed at session start, checkpoint insertion, and finish).
        let rawMeasuredEnergyWh = doubleValue(session, key: "measuredEnergyWh")
        let measuredEnergyWh: Double
        switch chargingTransportMode(for: session) {
        case .wired:
            measuredEnergyWh = rawMeasuredEnergyWh
        case .wireless:
            if let factor = optionalDoubleValue(session, key: "wirelessEfficiencyFactor"), factor > 0 {
                measuredEnergyWh = rawMeasuredEnergyWh * factor
            } else {
                measuredEnergyWh = optionalDoubleValue(session, key: "effectiveBatteryEnergyWh")
                    ?? rawMeasuredEnergyWh
            }
        }
        let sessionID = stringValue(session, key: "id") ?? ""

        struct Anchor {
            let percent: Double
            let energyWh: Double
            let timestamp: Date
            let isCheckpoint: Bool
        }

        var anchors: [Anchor] = []
        if let startBatteryPercent = optionalDoubleValue(session, key: "startBatteryPercent"),
           startBatteryPercent >= 0 {
            anchors.append(
                Anchor(
                    percent: startBatteryPercent,
                    energyWh: 0,
                    timestamp: dateValue(session, key: "trimStart")
                        ?? dateValue(session, key: "startedAt")
                        ?? Date.distantPast,
                    isCheckpoint: false
                )
            )
        }

        let checkpointAnchors = fetchCheckpointObjects(forSessionID: sessionID)
            .compactMap(makeCheckpointSummary(from:))
            .sorted { lhs, rhs in
                if lhs.measuredEnergyWh != rhs.measuredEnergyWh {
                    return lhs.measuredEnergyWh < rhs.measuredEnergyWh
                }
                return lhs.timestamp < rhs.timestamp
            }
            .filter { $0.batteryPercent >= 0 }
            .map {
                Anchor(
                    percent: $0.batteryPercent,
                    energyWh: $0.measuredEnergyWh,
                    timestamp: $0.timestamp,
                    isCheckpoint: true
                )
            }
        anchors.append(contentsOf: checkpointAnchors)

        guard !anchors.isEmpty else {
            return optionalDoubleValue(session, key: "endBatteryPercent")
        }

        let anchor = anchors.filter { $0.energyWh <= measuredEnergyWh + 0.05 }.last ?? anchors.first!
        return BatteryLevelPredictionTuning.predictedPercent(
            anchorPercent: anchor.percent,
            anchorEnergyWh: anchor.energyWh,
            anchorTimestamp: anchor.timestamp,
            anchorIsCheckpoint: anchor.isCheckpoint,
            effectiveEnergyWh: measuredEnergyWh,
            referenceTimestamp: dateValue(session, key: "lastObservedAt") ?? anchor.timestamp,
            estimatedCapacityWh: estimatedCapacityWh
        )
    }

    private func resolvedEstimatedBatteryCapacityWh(
        for session: NSManagedObject,
        chargedDevice: NSManagedObject
    ) -> Double? {
        if let sessionCapacityEstimate = optionalDoubleValue(session, key: "capacityEstimateWh"),
           sessionCapacityEstimate > 0 {
            return sessionCapacityEstimate
        }

        switch chargingTransportMode(for: session) {
        case .wired:
            return optionalDoubleValue(chargedDevice, key: "wiredEstimatedBatteryCapacityWh")
                ?? optionalDoubleValue(chargedDevice, key: "estimatedBatteryCapacityWh")
        case .wireless:
            return optionalDoubleValue(chargedDevice, key: "wirelessEstimatedBatteryCapacityWh")
                ?? optionalDoubleValue(chargedDevice, key: "estimatedBatteryCapacityWh")
        }
    }

    private func updateCapacityEstimate(for session: NSManagedObject) {
        guard
            let chargedDeviceID = stringValue(session, key: "chargedDeviceID"),
            let chargedDevice = fetchChargedDeviceObject(id: chargedDeviceID)
        else {
            session.setValue(nil, forKey: "effectiveBatteryEnergyWh")
            session.setValue(nil, forKey: "capacityEstimateWh")
            return
        }

        let measuredEnergyWh = doubleValue(session, key: "measuredEnergyWh")
        let chargingMode = chargingTransportMode(for: session)
        let wirelessResolution = chargingMode == .wireless
            ? resolvedWirelessEfficiency(for: session, chargedDevice: chargedDevice)
            : nil
        let effectiveBatteryEnergyWh = chargingMode == .wired
            ? measuredEnergyWh
            : wirelessResolution.map { measuredEnergyWh * $0.factor }

        session.setValue(effectiveBatteryEnergyWh, forKey: "effectiveBatteryEnergyWh")
        session.setValue(wirelessResolution?.factor, forKey: "wirelessEfficiencyFactor")
        session.setValue(wirelessResolution?.usesEstimated ?? false, forKey: "usesEstimatedWirelessEfficiency")
        session.setValue(wirelessResolution?.shouldWarn ?? false, forKey: "shouldWarnAboutLowWirelessEfficiency")

        let supportsChargingWhileOff = boolValue(chargedDevice, key: "supportsChargingWhileOff")

        guard let effectiveBatteryEnergyWh, effectiveBatteryEnergyWh > 0 else {
            session.setValue(nil, forKey: "capacityEstimateWh")
            return
        }

        struct CapacityAnchor {
            let percent: Double
            let energyWh: Double
            let timestamp: Date
        }

        var anchors: [CapacityAnchor] = []

        if let startBatteryPercent = optionalDoubleValue(session, key: "startBatteryPercent"),
           startBatteryPercent >= 0 {
            anchors.append(
                CapacityAnchor(
                    percent: startBatteryPercent,
                    energyWh: 0,
                    timestamp: dateValue(session, key: "trimStart")
                        ?? dateValue(session, key: "startedAt")
                        ?? Date.distantPast
                )
            )
        }

        if let sessionID = stringValue(session, key: "id") {
            anchors.append(
                contentsOf: fetchCheckpointObjects(forSessionID: sessionID).compactMap { checkpoint in
                    guard
                        let percent = optionalDoubleValue(checkpoint, key: "batteryPercent"),
                        percent >= 0,
                        let timestamp = dateValue(checkpoint, key: "timestamp")
                    else {
                        return nil
                    }

                    return CapacityAnchor(
                        percent: percent,
                        energyWh: doubleValue(checkpoint, key: "measuredEnergyWh"),
                        timestamp: timestamp
                    )
                }
            )
        }

        if let endBatteryPercent = optionalDoubleValue(session, key: "endBatteryPercent"),
           endBatteryPercent >= 0 {
            anchors.append(
                CapacityAnchor(
                    percent: endBatteryPercent,
                    energyWh: effectiveBatteryEnergyWh,
                    timestamp: dateValue(session, key: "endedAt")
                        ?? dateValue(session, key: "lastObservedAt")
                        ?? Date.distantPast
                )
            )
        }

        let sortedAnchors = anchors.sorted { lhs, rhs in
            if lhs.energyWh != rhs.energyWh {
                return lhs.energyWh < rhs.energyWh
            }
            return lhs.timestamp < rhs.timestamp
        }

        guard let firstAnchor = sortedAnchors.first,
              let lastAnchor = sortedAnchors.last else {
            session.setValue(nil, forKey: "capacityEstimateWh")
            return
        }

        let percentDelta = lastAnchor.percent - firstAnchor.percent
        let energyDelta = lastAnchor.energyWh - firstAnchor.energyWh

        guard percentDelta >= 20, energyDelta > 0 else {
            session.setValue(nil, forKey: "capacityEstimateWh")
            return
        }

        if !supportsChargingWhileOff && lastAnchor.percent >= 99.5 {
            session.setValue(nil, forKey: "capacityEstimateWh")
            return
        }

        let capacityEstimateWh = energyDelta / (percentDelta / 100)
        session.setValue(capacityEstimateWh, forKey: "capacityEstimateWh")
    }

    @discardableResult
    private func insertBatteryCheckpoint(
        percent: Double,
        flag: ChargeCheckpointFlag,
        timestamp: Date = Date(),
        measuredEnergyWhOverride: Double? = nil,
        measuredChargeAhOverride: Double? = nil,
        to session: NSManagedObject
    ) -> String? {
        guard
            let sessionID = stringValue(session, key: "id"),
            let chargedDeviceID = stringValue(session, key: "chargedDeviceID"),
            let entity = NSEntityDescription.entity(forEntityName: EntityName.chargeCheckpoint, in: context)
        else {
            return nil
        }

        let checkpoint = NSManagedObject(entity: entity, insertInto: context)
        let checkpointEnergyWh = measuredEnergyWhOverride
            ?? optionalDoubleValue(session, key: "effectiveBatteryEnergyWh")
            ?? doubleValue(session, key: "measuredEnergyWh")
        let checkpointChargeAh = measuredChargeAhOverride
            ?? doubleValue(session, key: "measuredChargeAh")
        checkpoint.setValue(UUID().uuidString, forKey: "id")
        checkpoint.setValue(sessionID, forKey: "sessionID")
        checkpoint.setValue(chargedDeviceID, forKey: "chargedDeviceID")
        checkpoint.setValue(timestamp, forKey: "timestamp")
        checkpoint.setValue(percent, forKey: "batteryPercent")
        checkpoint.setValue(checkpointEnergyWh, forKey: "measuredEnergyWh")
        checkpoint.setValue(checkpointChargeAh, forKey: "measuredChargeAh")
        checkpoint.setValue(doubleValue(session, key: "lastObservedCurrentAmps"), forKey: "currentAmps")
        checkpoint.setValue(
            chargingTransportMode(for: session) == .wired ? optionalDoubleValue(session, key: "lastObservedVoltageVolts") : nil,
            forKey: "voltageVolts"
        )
        checkpoint.setValue(flag.rawValue, forKey: "label")
        checkpoint.setValue(timestamp, forKey: "createdAt")

        let existingStartBatteryPercent = optionalDoubleValue(session, key: "startBatteryPercent")
        if existingStartBatteryPercent == nil || ((existingStartBatteryPercent ?? 0) < 0 && percent > 0) {
            session.setValue(percent, forKey: "startBatteryPercent")
        }
        if (existingStartBatteryPercent ?? 0) >= 0 || percent > 0 {
            session.setValue(percent, forKey: "endBatteryPercent")
        }
        session.setValue(timestamp, forKey: "updatedAt")
        updateCapacityEstimate(for: session)

        return chargedDeviceID
    }

    private func refreshCheckpointDerivedValues(for session: NSManagedObject) {
        guard let sessionID = stringValue(session, key: "id") else {
            return
        }

        let remainingCheckpoints = fetchCheckpointObjects(forSessionID: sessionID)
        if let latestCheckpoint = remainingCheckpoints.last {
            session.setValue(doubleValue(latestCheckpoint, key: "batteryPercent"), forKey: "endBatteryPercent")
        } else if let startBatteryPercent = optionalDoubleValue(session, key: "startBatteryPercent"),
                  startBatteryPercent >= 0 {
            session.setValue(startBatteryPercent, forKey: "endBatteryPercent")
        } else {
            session.setValue(nil, forKey: "endBatteryPercent")
        }

        session.setValue(Date(), forKey: "updatedAt")
        updateCapacityEstimate(for: session)
    }

    @discardableResult
    private func addBatteryCheckpoint(
        percent: Double,
        measuredEnergyWh: Double? = nil,
        measuredChargeAh: Double? = nil,
        flag: ChargeCheckpointFlag,
        to session: NSManagedObject,
        timestamp: Date = Date()
    ) -> Bool {
        if let measuredEnergyWh, measuredEnergyWh.isFinite {
            session.setValue(max(measuredEnergyWh, 0), forKey: "measuredEnergyWh")
        }
        if let measuredChargeAh, measuredChargeAh.isFinite {
            session.setValue(max(measuredChargeAh, 0), forKey: "measuredChargeAh")
        }

        guard let chargedDeviceID = insertBatteryCheckpoint(
            percent: percent,
            flag: flag,
            timestamp: timestamp,
            measuredEnergyWhOverride: measuredEnergyWh,
            measuredChargeAhOverride: measuredChargeAh,
            to: session
        ) else {
            return false
        }

        guard saveContext() else {
            return false
        }

        refreshDerivedMetrics(forChargedDeviceID: chargedDeviceID)
        return saveContext()
    }

    private func resolvedWirelessEfficiency(
        for session: NSManagedObject,
        chargedDevice: NSManagedObject
    ) -> (factor: Double, usesEstimated: Bool, shouldWarn: Bool)? {
        if let storedFactor = optionalDoubleValue(session, key: "wirelessEfficiencyFactor"),
           storedFactor > 0 {
            return (
                factor: storedFactor,
                usesEstimated: boolValue(session, key: "usesEstimatedWirelessEfficiency"),
                shouldWarn: boolValue(session, key: "shouldWarnAboutLowWirelessEfficiency")
            )
        }

        let chargingProfile = wirelessChargingProfile(for: chargedDevice)
        let measuredEnergyWh = doubleValue(session, key: "measuredEnergyWh")
        guard measuredEnergyWh > 0 else {
            return nil
        }

        if chargingProfile == .magsafe,
           let calibratedFactor = optionalDoubleValue(chargedDevice, key: "wirelessChargerEfficiencyFactor"),
           calibratedFactor > 0 {
            return (factor: calibratedFactor, usesEstimated: false, shouldWarn: false)
        }

        guard
            let startBatteryPercent = optionalDoubleValue(session, key: "startBatteryPercent"),
            let endBatteryPercent = optionalDoubleValue(session, key: "endBatteryPercent")
        else {
            return nil
        }

        let percentDelta = endBatteryPercent - startBatteryPercent
        guard percentDelta >= 20 else {
            return nil
        }

        guard let wiredCapacityWh = optionalDoubleValue(chargedDevice, key: "wiredEstimatedBatteryCapacityWh")
            ?? ((fallbackChargingTransportMode(for: chargedDevice) == .wired)
                ? optionalDoubleValue(chargedDevice, key: "estimatedBatteryCapacityWh")
                : nil),
              wiredCapacityWh > 0
        else {
            return nil
        }

        let deliveredBatteryEnergyWh = wiredCapacityWh * (percentDelta / 100)
        let rawFactor = deliveredBatteryEnergyWh / measuredEnergyWh
        let clampedFactor = min(max(rawFactor, minimumWirelessEfficiencyFactor), maximumWirelessEfficiencyFactor)
        let usesEstimated = chargingProfile != .magsafe
        let shouldWarn = usesEstimated && clampedFactor < lowWirelessEfficiencyThreshold

        return (factor: clampedFactor, usesEstimated: usesEstimated, shouldWarn: shouldWarn)
    }

    private func refreshDerivedMetrics(forChargedDeviceID chargedDeviceID: String) {
        guard let chargedDevice = fetchChargedDeviceObject(id: chargedDeviceID) else {
            return
        }

        let chargingStateAvailability = chargingStateAvailability(for: chargedDevice)
        let supportsChargingWhileOff = chargingStateAvailability.supportsChargingWhileOff
        let wirelessProfile = wirelessChargingProfile(for: chargedDevice)
        let deviceClass = ChargedDeviceClass(rawValue: stringValue(chargedDevice, key: "deviceClassRawValue") ?? "") ?? .other
        let sessions = relevantSessionObjects(
            for: chargedDeviceID,
            deviceClass: deviceClass,
            sessionsByDeviceID: [chargedDeviceID: fetchSessions(forChargedDeviceID: chargedDeviceID)],
            sessionsByChargerID: [chargedDeviceID: fetchSessions(forChargerID: chargedDeviceID)]
        )
        let learnedCompletionCurrents = derivedCompletionCurrents(from: sessions)
        let wiredMinimumCurrent = derivedMinimumCurrent(
            from: sessions,
            chargingTransportMode: .wired
        )
        let wirelessMinimumCurrent = derivedMinimumCurrent(
            from: sessions,
            chargingTransportMode: .wireless
        )

        let wiredCapacity = derivedCapacity(
            from: sessions,
            chargingTransportMode: .wired,
            supportsChargingWhileOff: supportsChargingWhileOff
        )
        let wirelessCapacity = derivedCapacity(
            from: sessions,
            chargingTransportMode: .wireless,
            supportsChargingWhileOff: supportsChargingWhileOff
        )
        let wirelessEfficiency = derivedWirelessEfficiency(
            from: sessions,
            chargingProfile: wirelessProfile
        )
        let configuredCompletionCurrents = decodedCompletionCurrents(
            from: chargedDevice,
            key: "configuredCompletionCurrentsRawValue"
        )
        let configuredWiredCompletionCurrent = optionalDoubleValue(chargedDevice, key: "wiredChargeCompletionCurrentAmps")
        let configuredWirelessCompletionCurrent = optionalDoubleValue(chargedDevice, key: "wirelessChargeCompletionCurrentAmps")
        let chargerObservedVoltages = deviceClass == .charger ? derivedObservedVoltageSelections(from: sessions) : []
        let chargerIdleCurrent = deviceClass == .charger ? derivedIdleCurrent(from: sessions) : nil
        let chargerEfficiency = deviceClass == .charger ? derivedChargerEfficiency(from: sessions) : nil
        let chargerMaximumPower = deviceClass == .charger ? derivedMaximumPower(from: sessions) : nil

        let preferredChargingTransportMode = fallbackChargingTransportMode(for: chargedDevice)
        let preferredChargingStateMode = chargingStateAvailability.supportedModes.first ?? .on
        let preferredMinimumCurrent: Double?
        let preferredCapacity: Double?
        switch preferredChargingTransportMode {
        case .wired:
            preferredMinimumCurrent = configuredCompletionCurrents[
                ChargeSessionKind(chargingTransportMode: .wired, chargingStateMode: preferredChargingStateMode)
            ] ?? learnedCompletionCurrents[
                ChargeSessionKind(chargingTransportMode: .wired, chargingStateMode: preferredChargingStateMode)
            ] ?? configuredWiredCompletionCurrent ?? wiredMinimumCurrent ?? configuredWirelessCompletionCurrent ?? wirelessMinimumCurrent
            preferredCapacity = wiredCapacity ?? wirelessCapacity
        case .wireless:
            preferredMinimumCurrent = configuredCompletionCurrents[
                ChargeSessionKind(chargingTransportMode: .wireless, chargingStateMode: preferredChargingStateMode)
            ] ?? learnedCompletionCurrents[
                ChargeSessionKind(chargingTransportMode: .wireless, chargingStateMode: preferredChargingStateMode)
            ] ?? configuredWirelessCompletionCurrent ?? wirelessMinimumCurrent ?? configuredWiredCompletionCurrent ?? wiredMinimumCurrent
            preferredCapacity = wirelessCapacity ?? wiredCapacity
        }

        setValue(wiredMinimumCurrent, on: chargedDevice, key: "wiredMinimumCurrentAmps")
        setValue(wirelessMinimumCurrent, on: chargedDevice, key: "wirelessMinimumCurrentAmps")
        setValue(encodedCompletionCurrents(learnedCompletionCurrents), on: chargedDevice, key: "learnedCompletionCurrentsRawValue")
        setValue(wiredCapacity, on: chargedDevice, key: "wiredEstimatedBatteryCapacityWh")
        setValue(wirelessCapacity, on: chargedDevice, key: "wirelessEstimatedBatteryCapacityWh")
        setValue(wirelessEfficiency, on: chargedDevice, key: "wirelessChargerEfficiencyFactor")
        setValue(encodedObservedVoltageSelections(chargerObservedVoltages), on: chargedDevice, key: "chargerObservedVoltageSelectionsRawValue")
        setValue(chargerIdleCurrent, on: chargedDevice, key: "chargerIdleCurrentAmps")
        setValue(chargerEfficiency, on: chargedDevice, key: "chargerEfficiencyFactor")
        setValue(chargerMaximumPower, on: chargedDevice, key: "chargerMaximumPowerWatts")
        setValue(preferredMinimumCurrent, on: chargedDevice, key: "minimumCurrentAmps")
        setValue(preferredCapacity, on: chargedDevice, key: "estimatedBatteryCapacityWh")
        setValue(Date(), on: chargedDevice, key: "updatedAt")
    }

    private func buildCapacityHistory(from sessions: [ChargeSessionSummary]) -> [CapacityTrendPoint] {
        sessions
            .filter { $0.status == .completed }
            .compactMap { session in
                guard let capacityEstimateWh = session.capacityEstimateWh else { return nil }
                let timestamp = session.endedAt ?? session.lastObservedAt
                return CapacityTrendPoint(
                    sessionID: session.id,
                    timestamp: timestamp,
                    capacityWh: capacityEstimateWh,
                    chargingTransportMode: session.chargingTransportMode
                )
            }
            .sorted { $0.timestamp < $1.timestamp }
    }

    private func buildTypicalCurve(from sessions: [ChargeSessionSummary]) -> [TypicalChargeCurvePoint] {
        var groupedEnergyByBin: [Int: [Double]] = [:]
        var groupedChargeByBin: [Int: [Double]] = [:]

        for session in sessions where session.status == .completed {
            let anchors = normalizedTypicalCurveAnchors(for: session)
            guard anchors.count >= 2 else {
                continue
            }

            for percentBin in stride(from: 0, through: 100, by: 10) {
                guard let interpolatedPoint = interpolatedTypicalCurvePoint(
                    for: Double(percentBin),
                    anchors: anchors
                ) else {
                    continue
                }

                groupedEnergyByBin[percentBin, default: []].append(interpolatedPoint.energyWh)
                groupedChargeByBin[percentBin, default: []].append(interpolatedPoint.chargeAh)
            }
        }

        let averagedPoints = groupedEnergyByBin.keys.sorted().compactMap { percentBin -> TypicalChargeCurvePoint? in
            guard
                let energies = groupedEnergyByBin[percentBin],
                let charges = groupedChargeByBin[percentBin],
                !energies.isEmpty,
                !charges.isEmpty
            else {
                return nil
            }

            return TypicalChargeCurvePoint(
                percentBin: percentBin,
                averageEnergyWh: energies.reduce(0, +) / Double(energies.count),
                averageChargeAh: charges.reduce(0, +) / Double(charges.count),
                sampleCount: min(energies.count, charges.count)
            )
        }

        var runningMaximumEnergyWh = 0.0
        var runningMaximumChargeAh = 0.0

        return averagedPoints.map { point in
            runningMaximumEnergyWh = max(runningMaximumEnergyWh, point.averageEnergyWh)
            runningMaximumChargeAh = max(runningMaximumChargeAh, point.averageChargeAh)
            return TypicalChargeCurvePoint(
                percentBin: point.percentBin,
                averageEnergyWh: runningMaximumEnergyWh,
                averageChargeAh: runningMaximumChargeAh,
                sampleCount: point.sampleCount
            )
        }
    }

    private func normalizedTypicalCurveAnchors(
        for session: ChargeSessionSummary
    ) -> [(percent: Double, energyWh: Double, chargeAh: Double)] {
        struct Anchor {
            let percent: Double
            let energyWh: Double
            let chargeAh: Double
            let timestamp: Date
        }

        var anchors: [Anchor] = session.checkpoints.compactMap { checkpoint in
            guard checkpoint.batteryPercent.isFinite,
                  checkpoint.measuredEnergyWh.isFinite,
                  checkpoint.measuredChargeAh.isFinite,
                  checkpoint.batteryPercent >= 0,
                  checkpoint.batteryPercent <= 100,
                  checkpoint.measuredEnergyWh >= 0,
                  checkpoint.measuredChargeAh >= 0 else {
                return nil
            }

            return Anchor(
                percent: checkpoint.batteryPercent,
                energyWh: checkpoint.measuredEnergyWh,
                chargeAh: checkpoint.measuredChargeAh,
                timestamp: checkpoint.timestamp
            )
        }

        if let startBatteryPercent = session.startBatteryPercent,
           startBatteryPercent.isFinite,
           startBatteryPercent >= 0,
           startBatteryPercent <= 100 {
            anchors.append(
                Anchor(
                    percent: startBatteryPercent,
                    energyWh: 0,
                    chargeAh: 0,
                    timestamp: session.startedAt
                )
            )
        }

        if let endBatteryPercent = session.endBatteryPercent,
           endBatteryPercent.isFinite,
           endBatteryPercent >= 0,
           endBatteryPercent <= 100 {
            anchors.append(
                Anchor(
                    percent: endBatteryPercent,
                    energyWh: session.effectiveBatteryEnergyWh ?? session.measuredEnergyWh,
                    chargeAh: session.measuredChargeAh,
                    timestamp: session.endedAt ?? session.lastObservedAt
                )
            )
        }

        let sortedAnchors = anchors.sorted { lhs, rhs in
            if lhs.percent != rhs.percent {
                return lhs.percent < rhs.percent
            }
            if lhs.energyWh != rhs.energyWh {
                return lhs.energyWh < rhs.energyWh
            }
            return lhs.timestamp < rhs.timestamp
        }

        var collapsedAnchors: [(percent: Double, energyWh: Double, chargeAh: Double)] = []

        for anchor in sortedAnchors {
            if let lastIndex = collapsedAnchors.indices.last,
               abs(collapsedAnchors[lastIndex].percent - anchor.percent) < 0.000_1 {
                collapsedAnchors[lastIndex] = (
                    percent: collapsedAnchors[lastIndex].percent,
                    energyWh: max(collapsedAnchors[lastIndex].energyWh, anchor.energyWh),
                    chargeAh: max(collapsedAnchors[lastIndex].chargeAh, anchor.chargeAh)
                )
            } else {
                collapsedAnchors.append(
                    (percent: anchor.percent, energyWh: anchor.energyWh, chargeAh: anchor.chargeAh)
                )
            }
        }

        var runningMaximumEnergyWh = 0.0
        var runningMaximumChargeAh = 0.0

        return collapsedAnchors.map { anchor in
            runningMaximumEnergyWh = max(runningMaximumEnergyWh, anchor.energyWh)
            runningMaximumChargeAh = max(runningMaximumChargeAh, anchor.chargeAh)
            return (
                percent: anchor.percent,
                energyWh: runningMaximumEnergyWh,
                chargeAh: runningMaximumChargeAh
            )
        }
    }

    private func interpolatedTypicalCurvePoint(
        for percent: Double,
        anchors: [(percent: Double, energyWh: Double, chargeAh: Double)]
    ) -> (energyWh: Double, chargeAh: Double)? {
        guard
            let firstAnchor = anchors.first,
            let lastAnchor = anchors.last,
            percent >= firstAnchor.percent,
            percent <= lastAnchor.percent
        else {
            return nil
        }

        if let exactAnchor = anchors.first(where: { abs($0.percent - percent) < 0.000_1 }) {
            return (energyWh: exactAnchor.energyWh, chargeAh: exactAnchor.chargeAh)
        }

        guard let upperIndex = anchors.firstIndex(where: { $0.percent > percent }),
              upperIndex > 0 else {
            return nil
        }

        let lowerAnchor = anchors[upperIndex - 1]
        let upperAnchor = anchors[upperIndex]
        let span = upperAnchor.percent - lowerAnchor.percent
        guard span > 0.000_1 else {
            return nil
        }

        let ratio = (percent - lowerAnchor.percent) / span
        let energyWh = lowerAnchor.energyWh + ((upperAnchor.energyWh - lowerAnchor.energyWh) * ratio)
        let chargeAh = lowerAnchor.chargeAh + ((upperAnchor.chargeAh - lowerAnchor.chargeAh) * ratio)
        return (energyWh: energyWh, chargeAh: chargeAh)
    }

    private func makeSessionSummary(
        from object: NSManagedObject,
        checkpoints: [NSManagedObject],
        samples: [NSManagedObject]
    ) -> ChargeSessionSummary? {
        let chargingTransportMode = chargingTransportMode(for: object)

        guard
            let id = uuidValue(object, key: "id"),
            let chargedDeviceID = uuidValue(object, key: "chargedDeviceID"),
            let startedAt = dateValue(object, key: "startedAt"),
            let lastObservedAt = dateValue(object, key: "lastObservedAt"),
            let status = statusValue(object, key: "statusRawValue"),
            let sourceMode = ChargeSessionSourceMode(rawValue: stringValue(object, key: "sourceModeRawValue") ?? "")
        else {
            return nil
        }

        let checkpointSummaries = checkpoints.compactMap(makeCheckpointSummary(from:))
            .sorted { $0.timestamp < $1.timestamp }
        let sampleSummaries = samples.compactMap(makeChargeSessionSampleSummary(from:))
            .sorted { lhs, rhs in
                if lhs.bucketIndex != rhs.bucketIndex {
                    return lhs.bucketIndex < rhs.bucketIndex
                }
                return lhs.timestamp < rhs.timestamp
            }

        return ChargeSessionSummary(
            id: id,
            chargedDeviceID: chargedDeviceID,
            chargerID: uuidValue(object, key: "chargerID"),
            meterMACAddress: stringValue(object, key: "meterMACAddress"),
            meterName: stringValue(object, key: "meterName"),
            meterModel: stringValue(object, key: "meterModel"),
            startedAt: startedAt,
            endedAt: dateValue(object, key: "endedAt"),
            lastObservedAt: lastObservedAt,
            pausedAt: dateValue(object, key: "pausedAt"),
            status: status,
            sourceMode: sourceMode,
            chargingTransportMode: chargingTransportMode,
            chargingStateMode: chargingStateMode(for: object),
            autoStopEnabled: boolValue(object, key: "autoStopEnabled"),
            measuredEnergyWh: doubleValue(object, key: "measuredEnergyWh"),
            effectiveBatteryEnergyWh: optionalDoubleValue(object, key: "effectiveBatteryEnergyWh"),
            measuredChargeAh: doubleValue(object, key: "measuredChargeAh"),
            meterEnergyBaselineWh: optionalDoubleValue(object, key: "meterEnergyBaselineWh"),
            meterChargeBaselineAh: optionalDoubleValue(object, key: "meterChargeBaselineAh"),
            meterDurationBaselineSeconds: optionalDoubleValue(object, key: "meterDurationBaselineSeconds"),
            meterLastDurationSeconds: optionalDoubleValue(object, key: "meterLastDurationSeconds"),
            minimumObservedCurrentAmps: optionalDoubleValue(object, key: "minimumObservedCurrentAmps"),
            maximumObservedCurrentAmps: optionalDoubleValue(object, key: "maximumObservedCurrentAmps"),
            maximumObservedPowerWatts: optionalDoubleValue(object, key: "maximumObservedPowerWatts"),
            maximumObservedVoltageVolts: chargingTransportMode == .wired
                ? optionalDoubleValue(object, key: "maximumObservedVoltageVolts")
                : nil,
            hasObservedChargeFlow: boolValue(object, key: "hasObservedChargeFlow"),
            selectedSourceVoltageVolts: optionalDoubleValue(object, key: "selectedSourceVoltageVolts"),
            completionCurrentAmps: optionalDoubleValue(object, key: "completionCurrentAmps"),
            stopThresholdAmps: doubleValue(object, key: "stopThresholdAmps"),
            startBatteryPercent: optionalDoubleValue(object, key: "startBatteryPercent"),
            endBatteryPercent: optionalDoubleValue(object, key: "endBatteryPercent"),
            capacityEstimateWh: optionalDoubleValue(object, key: "capacityEstimateWh"),
            wirelessEfficiencyFactor: optionalDoubleValue(object, key: "wirelessEfficiencyFactor"),
            usesEstimatedWirelessEfficiency: boolValue(object, key: "usesEstimatedWirelessEfficiency"),
            shouldWarnAboutLowWirelessEfficiency: boolValue(object, key: "shouldWarnAboutLowWirelessEfficiency"),
            supportsChargingWhileOff: boolValue(object, key: "supportsChargingWhileOff"),
            usedOfflineMeterCounters: boolValue(object, key: "usedOfflineMeterCounters"),
            targetBatteryPercent: optionalDoubleValue(object, key: "targetBatteryPercent"),
            targetBatteryAlertTriggeredAt: dateValue(object, key: "targetBatteryAlertTriggeredAt"),
            requiresCompletionConfirmation: boolValue(object, key: "requiresCompletionConfirmation"),
            completionConfirmationRequestedAt: dateValue(object, key: "completionConfirmationRequestedAt"),
            completionContradictionPercent: optionalDoubleValue(object, key: "completionContradictionPercent"),
            selectedDataGroup: optionalInt16Value(object, key: "selectedDataGroup").map(UInt8.init),
            trimStart: dateValue(object, key: "trimStart"),
            trimEnd: dateValue(object, key: "trimEnd"),
            checkpoints: checkpointSummaries,
            aggregatedSamples: sampleSummaries
        )
    }

    private func makeCheckpointSummary(from object: NSManagedObject) -> ChargeCheckpointSummary? {
        guard
            let id = uuidValue(object, key: "id"),
            let sessionID = uuidValue(object, key: "sessionID"),
            let chargedDeviceID = uuidValue(object, key: "chargedDeviceID"),
            let timestamp = dateValue(object, key: "timestamp")
        else {
            return nil
        }

        return ChargeCheckpointSummary(
            id: id,
            sessionID: sessionID,
            chargedDeviceID: chargedDeviceID,
            timestamp: timestamp,
            batteryPercent: doubleValue(object, key: "batteryPercent"),
            measuredEnergyWh: doubleValue(object, key: "measuredEnergyWh"),
            measuredChargeAh: doubleValue(object, key: "measuredChargeAh"),
            currentAmps: doubleValue(object, key: "currentAmps"),
            voltageVolts: optionalDoubleValue(object, key: "voltageVolts"),
            label: stringValue(object, key: "label")
        )
    }

    private func makeChargeSessionSampleSummary(from object: NSManagedObject) -> ChargeSessionSampleSummary? {
        guard
            let sessionID = uuidValue(object, key: "sessionID"),
            let chargedDeviceID = uuidValue(object, key: "chargedDeviceID"),
            let timestamp = dateValue(object, key: "timestamp")
        else {
            return nil
        }

        return ChargeSessionSampleSummary(
            sessionID: sessionID,
            chargedDeviceID: chargedDeviceID,
            bucketIndex: Int(optionalInt32Value(object, key: "bucketIndex") ?? 0),
            timestamp: timestamp,
            averageCurrentAmps: doubleValue(object, key: "averageCurrentAmps"),
            averageVoltageVolts: optionalDoubleValue(object, key: "averageVoltageVolts"),
            averagePowerWatts: doubleValue(object, key: "averagePowerWatts"),
            measuredEnergyWh: doubleValue(object, key: "measuredEnergyWh"),
            measuredChargeAh: doubleValue(object, key: "measuredChargeAh"),
            sampleCount: Int(optionalInt16Value(object, key: "sampleCount") ?? 0)
        )
    }

    private func fetchOpenSessionObject(forMeterMACAddress meterMACAddress: String) -> NSManagedObject? {
        fetchSessionObject(
            predicate: NSPredicate(
                format: "meterMACAddress == %@ AND (statusRawValue == %@ OR statusRawValue == %@)",
                normalizedMACAddress(meterMACAddress),
                ChargeSessionStatus.active.rawValue,
                ChargeSessionStatus.paused.rawValue
            )
        )
    }

    private func fetchOpenSessionObjects() -> [NSManagedObject] {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSession)
        request.predicate = NSPredicate(
            format: "statusRawValue == %@ OR statusRawValue == %@",
            ChargeSessionStatus.active.rawValue,
            ChargeSessionStatus.paused.rawValue
        )
        request.sortDescriptors = [NSSortDescriptor(key: "startedAt", ascending: true)]
        return (try? context.fetch(request)) ?? []
    }

    private func fetchActiveSessionObject(forMeterMACAddress meterMACAddress: String) -> NSManagedObject? {
        fetchSessionObject(
            predicate: NSPredicate(
                format: "meterMACAddress == %@ AND statusRawValue == %@",
                normalizedMACAddress(meterMACAddress),
                ChargeSessionStatus.active.rawValue
            )
        )
    }

    private func fetchSessionObject(predicate: NSPredicate) -> NSManagedObject? {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSession)
        request.predicate = predicate
        request.fetchLimit = 1
        request.sortDescriptors = [NSSortDescriptor(key: "startedAt", ascending: false)]
        return (try? context.fetch(request))?.first
    }

    private func fetchSessionObject(id: String) -> NSManagedObject? {
        fetchSessionObject(
            predicate: NSPredicate(format: "id == %@", id)
        )
    }

    private func fetchSessionSampleObject(sessionID: String, bucketIndex: Int32) -> NSManagedObject? {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSessionSample)
        request.predicate = NSPredicate(
            format: "sessionID == %@ AND bucketIndex == %d",
            sessionID,
            bucketIndex
        )
        request.fetchLimit = 1
        return (try? context.fetch(request))?.first
    }

    private func fetchSessionSampleObjects(forSessionID sessionID: String) -> [NSManagedObject] {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSessionSample)
        request.predicate = NSPredicate(format: "sessionID == %@", sessionID)
        return (try? context.fetch(request)) ?? []
    }

    private func fetchSessionSampleObjects(forSessionIDs sessionIDs: [String]) -> [NSManagedObject] {
        guard !sessionIDs.isEmpty else {
            return []
        }

        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSessionSample)
        request.predicate = NSPredicate(format: "sessionID IN %@", sessionIDs)
        return (try? context.fetch(request)) ?? []
    }

    private func fetchCheckpointObject(id: String, sessionID: String) -> NSManagedObject? {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeCheckpoint)
        request.predicate = NSPredicate(format: "id == %@ AND sessionID == %@", id, sessionID)
        request.fetchLimit = 1
        return (try? context.fetch(request))?.first
    }

    private func fetchCheckpointObjects(forSessionID sessionID: String) -> [NSManagedObject] {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeCheckpoint)
        request.predicate = NSPredicate(format: "sessionID == %@", sessionID)
        request.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: true)]
        return (try? context.fetch(request)) ?? []
    }

    private func fetchSessions(forChargedDeviceID chargedDeviceID: String) -> [NSManagedObject] {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSession)
        request.predicate = NSPredicate(format: "chargedDeviceID == %@", chargedDeviceID)
        request.sortDescriptors = [NSSortDescriptor(key: "startedAt", ascending: true)]
        return (try? context.fetch(request)) ?? []
    }

    private func fetchSessions(forChargerID chargerID: String) -> [NSManagedObject] {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSession)
        request.predicate = NSPredicate(format: "chargerID == %@", chargerID)
        request.sortDescriptors = [NSSortDescriptor(key: "startedAt", ascending: true)]
        return (try? context.fetch(request)) ?? []
    }

    private func sampleBackedSessionIDs(
        devices: [NSManagedObject],
        sessionsByDeviceID: [String: [NSManagedObject]],
        sessionsByChargerID: [String: [NSManagedObject]]
    ) -> Set<String> {
        var sessionIDs: Set<String> = []

        for device in devices {
            guard
                let deviceID = stringValue(device, key: "id"),
                let rawClass = stringValue(device, key: "deviceClassRawValue"),
                let deviceClass = ChargedDeviceClass(rawValue: rawClass)
            else {
                continue
            }

            let relevantSessions = relevantSessionObjects(
                for: deviceID,
                deviceClass: deviceClass,
                sessionsByDeviceID: sessionsByDeviceID,
                sessionsByChargerID: sessionsByChargerID
            )
            .sorted { lhs, rhs in
                let lhsStatus = statusValue(lhs, key: "statusRawValue") ?? .completed
                let rhsStatus = statusValue(rhs, key: "statusRawValue") ?? .completed

                if lhsStatus.isOpen && !rhsStatus.isOpen {
                    return true
                }
                if !lhsStatus.isOpen && rhsStatus.isOpen {
                    return false
                }

                return (dateValue(lhs, key: "startedAt") ?? .distantPast)
                    > (dateValue(rhs, key: "startedAt") ?? .distantPast)
            }

            var recentCompletedSamplesIncluded = 0

            for session in relevantSessions {
                guard let sessionID = stringValue(session, key: "id"),
                      let status = statusValue(session, key: "statusRawValue") else {
                    continue
                }

                if status.isOpen {
                    sessionIDs.insert(sessionID)
                    continue
                }

                guard recentCompletedSamplesIncluded < 2 else {
                    continue
                }

                sessionIDs.insert(sessionID)
                recentCompletedSamplesIncluded += 1
            }
        }

        return sessionIDs
    }

    private func relevantSessionObjects(
        for chargedDeviceID: String,
        deviceClass: ChargedDeviceClass,
        sessionsByDeviceID: [String: [NSManagedObject]],
        sessionsByChargerID: [String: [NSManagedObject]]
    ) -> [NSManagedObject] {
        let directSessions = sessionsByDeviceID[chargedDeviceID] ?? []
        guard deviceClass == .charger else {
            return directSessions
        }

        var seenSessionIDs = Set<String>()
        return (directSessions + (sessionsByChargerID[chargedDeviceID] ?? []))
            .filter { session in
                let sessionID = stringValue(session, key: "id") ?? UUID().uuidString
                return seenSessionIDs.insert(sessionID).inserted
            }
            .sorted {
                let lhsDate = dateValue($0, key: "startedAt") ?? .distantPast
                let rhsDate = dateValue($1, key: "startedAt") ?? .distantPast
                return lhsDate < rhsDate
            }
    }

    private func resolvedDeviceObject(for meterMACAddress: String) -> NSManagedObject? {
        resolvedAssignedObject(for: meterMACAddress, expectsChargerClass: false)
    }

    private func resolvedChargerObject(for meterMACAddress: String) -> NSManagedObject? {
        resolvedAssignedObject(for: meterMACAddress, expectsChargerClass: true)
    }

    private func resolvedAssignedObject(
        for meterMACAddress: String,
        expectsChargerClass: Bool
    ) -> NSManagedObject? {
        let normalizedMAC = normalizedMACAddress(meterMACAddress)
        guard !normalizedMAC.isEmpty else { return nil }

        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargedDevice)
        request.predicate = NSPredicate(format: "lastAssociatedMeterMAC == %@", normalizedMAC)
        request.sortDescriptors = [NSSortDescriptor(key: "updatedAt", ascending: false)]
        let matches = (try? context.fetch(request)) ?? []
        return matches.first { object in
            isChargerObject(object) == expectsChargerClass
        }
    }

    private func isChargerObject(_ object: NSManagedObject) -> Bool {
        ChargedDeviceClass(rawValue: stringValue(object, key: "deviceClassRawValue") ?? "") == .charger
    }

    private func fetchChargedDeviceObject(id: String) -> NSManagedObject? {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargedDevice)
        request.predicate = NSPredicate(format: "id == %@", id)
        request.fetchLimit = 1
        return (try? context.fetch(request))?.first
    }

    private func fetchObjects(entityName: String) -> [NSManagedObject] {
        let request = NSFetchRequest<NSManagedObject>(entityName: entityName)
        return (try? context.fetch(request)) ?? []
    }

    private func resolvedStopThreshold(
        for chargedDevice: NSManagedObject,
        chargingTransportMode: ChargingTransportMode,
        chargingStateMode: ChargingStateMode,
        charger: NSManagedObject?,
        fallback: Double?
    ) -> Double? {
        if chargingTransportMode == .wireless, chargerIdleCurrent(for: charger) == nil {
            return nil
        }

        let sessionKind = ChargeSessionKind(
            chargingTransportMode: chargingTransportMode,
            chargingStateMode: chargingStateMode
        )
        let configuredCurrents = decodedCompletionCurrents(
            from: chargedDevice,
            key: "configuredCompletionCurrentsRawValue"
        )
        let learnedCurrents = decodedCompletionCurrents(
            from: chargedDevice,
            key: "learnedCompletionCurrentsRawValue"
        )
        let legacyCurrent: Double?
        switch chargingTransportMode {
        case .wired:
            legacyCurrent = optionalDoubleValue(chargedDevice, key: "wiredChargeCompletionCurrentAmps")
                ?? optionalDoubleValue(chargedDevice, key: "wiredMinimumCurrentAmps")
                ?? optionalDoubleValue(chargedDevice, key: "minimumCurrentAmps")
        case .wireless:
            legacyCurrent = optionalDoubleValue(chargedDevice, key: "wirelessChargeCompletionCurrentAmps")
                ?? optionalDoubleValue(chargedDevice, key: "wirelessMinimumCurrentAmps")
                ?? optionalDoubleValue(chargedDevice, key: "minimumCurrentAmps")
        }

        let resolvedCurrent = configuredCurrents[sessionKind]
            ?? learnedCurrents[sessionKind]
            ?? legacyCurrent
            ?? fallback
        guard let resolvedCurrent, resolvedCurrent > 0 else {
            return nil
        }
        return max(resolvedCurrent, 0.01)
    }

    private func fallbackChargingTransportMode(for chargedDevice: NSManagedObject) -> ChargingTransportMode {
        let supportsWiredCharging = supportsWiredCharging(for: chargedDevice)
        let supportsWirelessCharging = supportsWirelessCharging(for: chargedDevice)
        return resolvedPreferredChargingTransportMode(
            .wired,
            supportsWiredCharging: supportsWiredCharging,
            supportsWirelessCharging: supportsWirelessCharging
        )
    }

    private func deviceClass(for object: NSManagedObject) -> ChargedDeviceClass {
        ChargedDeviceClass(rawValue: stringValue(object, key: "deviceClassRawValue") ?? "") ?? .other
    }

    private func normalizedTemplateID(
        _ templateID: String?,
        kind: ChargedDeviceKind
    ) -> String? {
        guard let templateID,
              let templateDefinition = ChargedDeviceTemplateCatalog.shared.template(id: templateID),
              templateDefinition.kind == kind else {
            return nil
        }
        return templateDefinition.id
    }

    private func templateDefinition(for chargedDevice: NSManagedObject) -> ChargedDeviceTemplateDefinition? {
        guard let templateID = stringValue(chargedDevice, key: "deviceTemplateID"),
              let templateDefinition = ChargedDeviceTemplateCatalog.shared.template(id: templateID),
              templateDefinition.kind == deviceClass(for: chargedDevice).kind else {
            return nil
        }
        return templateDefinition
    }

    private func supportsWiredCharging(for chargedDevice: NSManagedObject) -> Bool {
        let persistedWiredCharging = chargedDevice.value(forKey: "supportsWiredCharging") == nil
            ? true
            : boolValue(chargedDevice, key: "supportsWiredCharging")
        let persistedWirelessCharging = chargedDevice.value(forKey: "supportsWirelessCharging") == nil
            ? false
            : boolValue(chargedDevice, key: "supportsWirelessCharging")
        return deviceClass(for: chargedDevice).normalizedChargingSupport(
            supportsWiredCharging: persistedWiredCharging,
            supportsWirelessCharging: persistedWirelessCharging
        ).wired
    }

    private func supportsWirelessCharging(for chargedDevice: NSManagedObject) -> Bool {
        let persistedWiredCharging = chargedDevice.value(forKey: "supportsWiredCharging") == nil
            ? true
            : boolValue(chargedDevice, key: "supportsWiredCharging")
        let persistedWirelessCharging = chargedDevice.value(forKey: "supportsWirelessCharging") == nil
            ? false
            : boolValue(chargedDevice, key: "supportsWirelessCharging")
        return deviceClass(for: chargedDevice).normalizedChargingSupport(
            supportsWiredCharging: persistedWiredCharging,
            supportsWirelessCharging: persistedWirelessCharging
        ).wireless
    }

    private func chargingStateAvailability(for chargedDevice: NSManagedObject) -> ChargingStateAvailability {
        let persistedAvailability = stringValue(chargedDevice, key: "chargingStateAvailabilityRawValue")
            .flatMap(ChargingStateAvailability.init(rawValue:))
            ?? ChargingStateAvailability.fallback(
            for: boolValue(chargedDevice, key: "supportsChargingWhileOff")
        )
        return deviceClass(for: chargedDevice).normalizedChargingStateAvailability(persistedAvailability)
    }

    private func chargingStateMode(for session: NSManagedObject) -> ChargingStateMode {
        if let chargedDeviceID = stringValue(session, key: "chargedDeviceID"),
           let chargedDevice = fetchChargedDeviceObject(id: chargedDeviceID) {
            let persistedChargingStateMode = stringValue(session, key: "chargingStateRawValue")
                .flatMap(ChargingStateMode.init(rawValue:))
                ?? .on
            return resolvedChargingStateMode(
                persistedChargingStateMode,
                availability: chargingStateAvailability(for: chargedDevice)
            )
        }

        if let rawValue = stringValue(session, key: "chargingStateRawValue"),
           let chargingStateMode = ChargingStateMode(rawValue: rawValue) {
            return chargingStateMode
        }

        return .on
    }

    private func resolvedChargingStateMode(
        _ chargingStateMode: ChargingStateMode,
        availability: ChargingStateAvailability
    ) -> ChargingStateMode {
        if availability.supportedModes.contains(chargingStateMode) {
            return chargingStateMode
        }
        return availability.supportedModes.first ?? .on
    }

    private func chargerType(for chargedDevice: NSManagedObject) -> ChargerType? {
        let deviceClass = ChargedDeviceClass(rawValue: stringValue(chargedDevice, key: "deviceClassRawValue") ?? "") ?? .other
        guard deviceClass == .charger else { return nil }

        // Primary: chargerTypeRawValue (set on v13+)
        if let rawValue = stringValue(chargedDevice, key: "chargerTypeRawValue"),
           let type = ChargerType(rawValue: rawValue) {
            return type
        }

        // Migration fallback: derive from old deviceTemplateID
        switch stringValue(chargedDevice, key: "deviceTemplateID") {
        case "apple-magsafe-charger": return .appleMagSafe
        case "apple-watch-charger": return .appleWatch
        default: break
        }

        // Last resort: derive from wirelessChargingProfileRawValue
        if let rawValue = stringValue(chargedDevice, key: "wirelessChargingProfileRawValue"),
           let profile = WirelessChargingProfile(rawValue: rawValue),
           profile == .magsafe {
            return .genericMagSafe
        }

        return .genericQi
    }

    private func wirelessChargingProfile(for chargedDevice: NSManagedObject) -> WirelessChargingProfile {
        if let type = chargerType(for: chargedDevice) {
            return type.wirelessChargingProfile
        }
        guard let rawValue = stringValue(chargedDevice, key: "wirelessChargingProfileRawValue"),
              let profile = WirelessChargingProfile(rawValue: rawValue) else {
            return .genericQi
        }
        return profile
    }

    private func resolvedPreferredChargingTransportMode(
        _ preferredChargingTransportMode: ChargingTransportMode,
        supportsWiredCharging: Bool,
        supportsWirelessCharging: Bool
    ) -> ChargingTransportMode {
        switch preferredChargingTransportMode {
        case .wired where supportsWiredCharging:
            return .wired
        case .wireless where supportsWirelessCharging:
            return .wireless
        default:
            if supportsWiredCharging {
                return .wired
            }
            if supportsWirelessCharging {
                return .wireless
            }
            return .wired
        }
    }

    private func encodedCompletionCurrents(_ currents: [ChargeSessionKind: Double]) -> String? {
        let payload = Dictionary(
            uniqueKeysWithValues: currents.map { key, value in
                (key.rawValue, value)
            }
        )
        guard let data = try? JSONSerialization.data(withJSONObject: payload, options: [.sortedKeys]) else {
            return nil
        }
        return String(data: data, encoding: .utf8)
    }

    private func decodedCompletionCurrents(
        from object: NSManagedObject,
        key: String
    ) -> [ChargeSessionKind: Double] {
        guard let rawValue = stringValue(object, key: key),
              let data = rawValue.data(using: .utf8),
              let payload = try? JSONSerialization.jsonObject(with: data) as? [String: Double] else {
            return [:]
        }

        return payload.reduce(into: [ChargeSessionKind: Double]()) { result, entry in
            guard let sessionKind = ChargeSessionKind(rawValue: entry.key), entry.value > 0 else {
                return
            }
            result[sessionKind] = entry.value
        }
    }

    private func legacyConfiguredCompletionCurrent(
        for currents: [ChargeSessionKind: Double],
        chargingTransportMode: ChargingTransportMode
    ) -> Double? {
        let candidates = currents
            .filter { $0.key.chargingTransportMode == chargingTransportMode }
            .sorted { lhs, rhs in
                lhs.key.rawValue < rhs.key.rawValue
            }
            .map(\.value)
        return candidates.first
    }

    private func chargerIdleCurrent(for charger: NSManagedObject?) -> Double? {
        guard let charger else {
            return nil
        }
        let idleCurrent = optionalDoubleValue(charger, key: "chargerIdleCurrentAmps")
        guard let idleCurrent, idleCurrent >= 0 else {
            return nil
        }
        return idleCurrent
    }

    private func effectiveCurrentAmps(
        fromMeasuredCurrent currentAmps: Double,
        chargingTransportMode: ChargingTransportMode,
        charger: NSManagedObject?
    ) -> Double {
        switch chargingTransportMode {
        case .wired:
            return max(currentAmps, 0)
        case .wireless:
            guard let idleCurrent = chargerIdleCurrent(for: charger) else {
                return max(currentAmps, 0)
            }
            return max(currentAmps - idleCurrent, 0)
        }
    }

    private func hasObservedChargeFlow(
        currentAmps: Double,
        chargingTransportMode: ChargingTransportMode,
        charger: NSManagedObject?,
        stopThreshold: Double?
    ) -> Bool {
        let effectiveCurrent = effectiveCurrentAmps(
            fromMeasuredCurrent: currentAmps,
            chargingTransportMode: chargingTransportMode,
            charger: charger
        )
        return effectiveCurrent > max(stopThreshold ?? 0, 0.05)
    }

    private func hasSavableChargeData(_ session: NSManagedObject) -> Bool {
        boolValue(session, key: "hasObservedChargeFlow")
            || doubleValue(session, key: "measuredEnergyWh") > 0
            || doubleValue(session, key: "measuredChargeAh") > 0
            || (optionalDoubleValue(session, key: "maximumObservedCurrentAmps") ?? 0) > 0
            || (optionalDoubleValue(session, key: "maximumObservedPowerWatts") ?? 0) > 0
    }

    private func derivedMinimumCurrent(
        from sessions: [NSManagedObject],
        chargingTransportMode: ChargingTransportMode
    ) -> Double? {
        let completionCurrents = sessions.compactMap { session -> Double? in
            guard statusValue(session, key: "statusRawValue") == .completed else { return nil }
            guard self.chargingTransportMode(for: session) == chargingTransportMode else {
                return nil
            }
            guard (optionalDoubleValue(session, key: "endBatteryPercent") ?? 0) >= 99.5 else {
                return nil
            }
            guard let completionCurrent = optionalDoubleValue(session, key: "completionCurrentAmps"), completionCurrent > 0 else {
                return nil
            }
            return completionCurrent
        }

        let recentCompletionCurrents = Array(completionCurrents.suffix(5))
        guard !recentCompletionCurrents.isEmpty else { return nil }
        return recentCompletionCurrents.reduce(0, +) / Double(recentCompletionCurrents.count)
    }

    private func derivedCompletionCurrents(from sessions: [NSManagedObject]) -> [ChargeSessionKind: Double] {
        var groupedCurrents: [ChargeSessionKind: [Double]] = [:]

        for session in sessions {
            guard statusValue(session, key: "statusRawValue") == .completed else {
                continue
            }
            guard (optionalDoubleValue(session, key: "endBatteryPercent") ?? 0) >= 99.5 else {
                continue
            }
            guard let completionCurrent = optionalDoubleValue(session, key: "completionCurrentAmps"),
                  completionCurrent > 0 else {
                continue
            }

            let sessionKind = ChargeSessionKind(
                chargingTransportMode: chargingTransportMode(for: session),
                chargingStateMode: chargingStateMode(for: session)
            )
            groupedCurrents[sessionKind, default: []].append(completionCurrent)
        }

        return groupedCurrents.reduce(into: [ChargeSessionKind: Double]()) { result, entry in
            let recentCurrents = Array(entry.value.suffix(5))
            guard !recentCurrents.isEmpty else {
                return
            }
            result[entry.key] = recentCurrents.reduce(0, +) / Double(recentCurrents.count)
        }
    }

    private func derivedCapacity(
        from sessions: [NSManagedObject],
        chargingTransportMode: ChargingTransportMode,
        supportsChargingWhileOff: Bool
    ) -> Double? {
        let capacityCandidates = sessions.compactMap { session -> Double? in
            guard statusValue(session, key: "statusRawValue") == .completed else { return nil }
            guard self.chargingTransportMode(for: session) == chargingTransportMode else {
                return nil
            }
            guard let capacityEstimate = optionalDoubleValue(session, key: "capacityEstimateWh"), capacityEstimate > 0 else {
                return nil
            }
            if supportsChargingWhileOff {
                return capacityEstimate
            }
            guard let endBatteryPercent = optionalDoubleValue(session, key: "endBatteryPercent"), endBatteryPercent < 99.5 else {
                return nil
            }
            return capacityEstimate
        }

        let recentCapacityCandidates = Array(capacityCandidates.suffix(6))
        guard !recentCapacityCandidates.isEmpty else { return nil }
        return recentCapacityCandidates.reduce(0, +) / Double(recentCapacityCandidates.count)
    }

    private func derivedWirelessEfficiency(
        from sessions: [NSManagedObject],
        chargingProfile: WirelessChargingProfile
    ) -> Double? {
        guard chargingProfile == .magsafe else {
            return nil
        }

        let candidates = sessions.compactMap { session -> Double? in
            guard statusValue(session, key: "statusRawValue") == .completed else { return nil }
            guard chargingTransportMode(for: session) == .wireless else { return nil }
            guard boolValue(session, key: "usesEstimatedWirelessEfficiency") == false else { return nil }
            guard let factor = optionalDoubleValue(session, key: "wirelessEfficiencyFactor"), factor > 0 else {
                return nil
            }
            return factor
        }

        let recentCandidates = Array(candidates.suffix(6))
        guard !recentCandidates.isEmpty else { return nil }
        return recentCandidates.reduce(0, +) / Double(recentCandidates.count)
    }

    private func derivedObservedVoltageSelections(from sessions: [NSManagedObject]) -> [Double] {
        let candidates = sessions.compactMap { session -> Double? in
            guard statusValue(session, key: "statusRawValue") == .completed else { return nil }
            guard let sourceVoltage = optionalDoubleValue(session, key: "selectedSourceVoltageVolts"), sourceVoltage > 0 else {
                return nil
            }
            return (sourceVoltage * 10).rounded() / 10
        }

        let counts = Dictionary(grouping: candidates, by: { $0 }).mapValues(\.count)
        return counts.keys.sorted()
    }

    private func derivedIdleCurrent(from sessions: [NSManagedObject]) -> Double? {
        let candidates = sessions.compactMap { session -> Double? in
            guard statusValue(session, key: "statusRawValue") == .completed else { return nil }
            guard let minimumObservedCurrent = optionalDoubleValue(session, key: "minimumObservedCurrentAmps"), minimumObservedCurrent > 0 else {
                return nil
            }
            return minimumObservedCurrent
        }

        let recentCandidates = Array(candidates.suffix(6))
        guard !recentCandidates.isEmpty else { return nil }
        return recentCandidates.reduce(0, +) / Double(recentCandidates.count)
    }

    private func derivedChargerEfficiency(from sessions: [NSManagedObject]) -> Double? {
        let candidates = sessions.compactMap { session -> Double? in
            guard statusValue(session, key: "statusRawValue") == .completed else { return nil }
            guard let factor = optionalDoubleValue(session, key: "wirelessEfficiencyFactor"), factor > 0 else {
                return nil
            }
            return factor
        }

        let recentCandidates = Array(candidates.suffix(6))
        guard !recentCandidates.isEmpty else { return nil }
        return recentCandidates.reduce(0, +) / Double(recentCandidates.count)
    }

    private func derivedMaximumPower(from sessions: [NSManagedObject]) -> Double? {
        sessions.compactMap { session -> Double? in
            guard statusValue(session, key: "statusRawValue") == .completed else { return nil }
            guard let maximumObservedPower = optionalDoubleValue(session, key: "maximumObservedPowerWatts"), maximumObservedPower > 0 else {
                return nil
            }
            return maximumObservedPower
        }
        .max()
    }

    private func chargingTransportMode(for session: NSManagedObject) -> ChargingTransportMode {
        if let chargedDeviceID = stringValue(session, key: "chargedDeviceID"),
           let chargedDevice = fetchChargedDeviceObject(id: chargedDeviceID) {
            return resolvedPreferredChargingTransportMode(
                chargingTransportModeValue(session, key: "chargingTransportRawValue") ?? .wired,
                supportsWiredCharging: supportsWiredCharging(for: chargedDevice),
                supportsWirelessCharging: supportsWirelessCharging(for: chargedDevice)
            )
        }

        if let persistedChargingTransportMode = chargingTransportModeValue(session, key: "chargingTransportRawValue") {
            return persistedChargingTransportMode
        }

        return .wired
    }

    private func saveReason(for session: NSManagedObject, observedAt: Date) -> ObservationSaveReason {
        if session.isInserted {
            return .created
        }

        let committedValues = session.committedValues(
            forKeys: [
                "statusRawValue",
                "updatedAt",
                "targetBatteryAlertTriggeredAt",
                "requiresCompletionConfirmation"
            ]
        )
        let committedStatus = (committedValues["statusRawValue"] as? String).flatMap(ChargeSessionStatus.init(rawValue:))
        let currentStatus = statusValue(session, key: "statusRawValue")
        let committedTargetAlertTriggeredAt = committedValues["targetBatteryAlertTriggeredAt"] as? Date
        let currentTargetAlertTriggeredAt = dateValue(session, key: "targetBatteryAlertTriggeredAt")
        let committedRequiresCompletionConfirmation = (committedValues["requiresCompletionConfirmation"] as? NSNumber)?.boolValue
            ?? (committedValues["requiresCompletionConfirmation"] as? Bool)
            ?? false
        let currentRequiresCompletionConfirmation = boolValue(session, key: "requiresCompletionConfirmation")

        if currentStatus == .completed, committedStatus != .completed {
            return .completed
        }

        if currentStatus != committedStatus {
            return .event
        }

        if committedTargetAlertTriggeredAt != currentTargetAlertTriggeredAt
            || committedRequiresCompletionConfirmation != currentRequiresCompletionConfirmation {
            return .event
        }

        let lastPersistedAt = (committedValues["updatedAt"] as? Date)
            ?? dateValue(session, key: "createdAt")
            ?? observedAt

        if observedAt.timeIntervalSince(lastPersistedAt) >= activeSessionSaveInterval {
            return .periodic
        }

        return .none
    }

    private func shouldPersistAggregatedSample(
        _ sample: NSManagedObject,
        observedAt: Date
    ) -> Bool {
        if sample.isInserted {
            return true
        }

        let committedValues = sample.committedValues(forKeys: ["updatedAt"])
        let lastPersistedAt = (committedValues["updatedAt"] as? Date)
            ?? dateValue(sample, key: "createdAt")
            ?? observedAt

        return observedAt.timeIntervalSince(lastPersistedAt) >= aggregatedSampleSaveInterval
    }

    private func generateQRIdentifier() -> String {
        "device:\(UUID().uuidString)"
    }

    @discardableResult
    private func saveContext() -> Bool {
        guard context.hasChanges else { return true }
        do {
            try context.save()
            return true
        } catch {
            track("Failed saving charge insights context: \(error)")
            context.rollback()
            return false
        }
    }

    private func normalizedText(_ text: String) -> String {
        text.trimmingCharacters(in: .whitespacesAndNewlines)
    }

    private func normalizedOptionalText(_ text: String?) -> String? {
        guard let text else { return nil }
        let normalized = normalizedText(text)
        return normalized.isEmpty ? nil : normalized
    }

    private func normalizedMACAddress(_ macAddress: String) -> String {
        normalizedText(macAddress).uppercased()
    }

    private func rawValue(_ object: NSManagedObject, key: String) -> Any? {
        guard object.entity.propertiesByName[key] != nil else {
            return nil
        }
        return object.value(forKey: key)
    }

    private func setValue(_ value: Any?, on object: NSManagedObject, key: String) {
        guard object.entity.propertiesByName[key] != nil else {
            return
        }
        object.setValue(value, forKey: key)
    }

    private func stringValue(_ object: NSManagedObject, key: String) -> String? {
        guard let value = rawValue(object, key: key) as? String else { return nil }
        let normalized = normalizedOptionalText(value)
        return normalized
    }

    private func dateValue(_ object: NSManagedObject, key: String) -> Date? {
        rawValue(object, key: key) as? Date
    }

    private func doubleValue(_ object: NSManagedObject, key: String) -> Double {
        if let value = rawValue(object, key: key) as? Double {
            return value
        }
        if let value = rawValue(object, key: key) as? NSNumber {
            return value.doubleValue
        }
        return 0
    }

    private func optionalDoubleValue(_ object: NSManagedObject, key: String) -> Double? {
        let value = rawValue(object, key: key)
        if value == nil {
            return nil
        }
        return doubleValue(object, key: key)
    }

    private func optionalInt16Value(_ object: NSManagedObject, key: String) -> Int16? {
        if let value = rawValue(object, key: key) as? Int16 {
            return value
        }
        if let value = rawValue(object, key: key) as? NSNumber {
            return value.int16Value
        }
        return nil
    }

    private func optionalInt32Value(_ object: NSManagedObject, key: String) -> Int32? {
        if let value = rawValue(object, key: key) as? Int32 {
            return value
        }
        if let value = rawValue(object, key: key) as? NSNumber {
            return value.int32Value
        }
        return nil
    }

    private func boolValue(_ object: NSManagedObject, key: String) -> Bool {
        if let value = rawValue(object, key: key) as? Bool {
            return value
        }
        if let value = rawValue(object, key: key) as? NSNumber {
            return value.boolValue
        }
        return false
    }

    private func uuidValue(_ object: NSManagedObject, key: String) -> UUID? {
        guard let value = stringValue(object, key: key) else { return nil }
        return UUID(uuidString: value)
    }

    private func statusValue(_ object: NSManagedObject, key: String) -> ChargeSessionStatus? {
        guard let value = stringValue(object, key: key) else { return nil }
        return ChargeSessionStatus(rawValue: value)
    }

    private func chargingTransportModeValue(_ object: NSManagedObject, key: String) -> ChargingTransportMode? {
        guard let value = stringValue(object, key: key) else { return nil }
        return ChargingTransportMode(rawValue: value)
    }

    private func decodedObservedVoltageSelections(from object: NSManagedObject) -> [Double] {
        guard let rawValue = stringValue(object, key: "chargerObservedVoltageSelectionsRawValue") else {
            return []
        }
        return rawValue
            .split(separator: ",")
            .compactMap { Double($0) }
            .sorted()
    }

    private func encodedObservedVoltageSelections(_ voltages: [Double]) -> String? {
        let uniqueVoltages = Array(Set(voltages)).sorted()
        guard !uniqueVoltages.isEmpty else {
            return nil
        }
        return uniqueVoltages
            .map { String(format: "%.1f", $0) }
            .joined(separator: ",")
    }

    private func runningAverage(currentAverage: Double, currentCount: Int, newValue: Double) -> Double {
        guard currentCount > 0 else {
            return newValue
        }
        let total = (currentAverage * Double(currentCount)) + newValue
        return total / Double(currentCount + 1)
    }
}

private enum ObservationSaveReason {
    case none
    case created
    case periodic
    case completed
    case event
}
