//
//  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 powerbank = "Powerbank"
        static let chargeSession = "ChargeSession"
        static let chargeCheckpoint = "ChargeCheckpoint"
        static let chargeSessionSample = "ChargeSessionSample"
        static let deviceProfile = "DeviceProfile"
    }

    private static let maximumChargeSessionDuration: TimeInterval = 12 * 60 * 60
    private static let persistedSamplesPerHour = 300
    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 seedDeviceProfilesCatalog(_ profiles: [DeviceProfileDefinition]) -> Bool {
        var didSave = false
        context.performAndWait {
            let now = Date()
            let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.deviceProfile)
            request.predicate = NSPredicate(format: "isCustom == NO OR isCustom == nil")
            let existing = (try? context.fetch(request)) ?? []
            let existingByID: [String: NSManagedObject] = Dictionary(
                grouping: existing,
                by: { stringValue($0, key: "id") ?? "" }
            ).compactMapValues { $0.first }

            for profile in profiles {
                let target: NSManagedObject
                if let row = existingByID[profile.id] {
                    target = row
                } else {
                    target = NSEntityDescription.insertNewObject(
                        forEntityName: EntityName.deviceProfile,
                        into: context
                    )
                    setValue(profile.id, on: target, key: "id")
                    setValue(now, on: target, key: "createdAt")
                }
                applyCatalogProfile(profile, to: target, updatedAt: now)
            }

            didSave = saveContext()
        }
        return didSave
    }

    /// Backfills `profileID` on all ChargedDevice and Powerbank rows that lack one,
    /// and promotes legacy `ChargedDevice` rows with `deviceClass == "powerbank"` to
    /// the dedicated `Powerbank` entity. Idempotent — re-running has no effect once
    /// every row has a `profileID` and no legacy powerbank-class rows remain.
    @discardableResult
    func migrateDevicesToProfiles() -> Bool {
        var didSave = false
        context.performAndWait {
            let now = Date()
            var didChange = false

            // 1. ChargedDevices (including chargers): assign profileID where missing.
            let deviceRequest = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargedDevice)
            let devices = (try? context.fetch(deviceRequest)) ?? []

            // 1a. Promote legacy class-`.powerbank` rows to the Powerbank entity.
            for device in devices {
                guard stringValue(device, key: "deviceClassRawValue") == ChargedDeviceClass.powerbank.rawValue else {
                    continue
                }
                promoteLegacyPowerbankDevice(device, now: now)
                didChange = true
            }

            // 1b. Backfill profileID for the remaining (non-powerbank-class) devices.
            for device in devices where !device.isDeleted {
                guard stringValue(device, key: "profileID") == nil else { continue }
                guard stringValue(device, key: "deviceClassRawValue") != ChargedDeviceClass.powerbank.rawValue else {
                    // Already handled (and deleted) in 1a.
                    continue
                }

                let assignedProfileID = resolveProfileIDForLegacyDevice(device, now: now)
                setValue(assignedProfileID, on: device, key: "profileID")
                setValue(now, on: device, key: "updatedAt")
                didChange = true
            }

            // 2. Powerbanks: backfill profileID where missing.
            let powerbankRequest = NSFetchRequest<NSManagedObject>(entityName: EntityName.powerbank)
            let powerbanks = (try? context.fetch(powerbankRequest)) ?? []
            for powerbank in powerbanks where !powerbank.isDeleted {
                guard stringValue(powerbank, key: "profileID") == nil else { continue }

                let templateID = stringValue(powerbank, key: "deviceTemplateID")
                let assignedProfileID: String
                if let templateID,
                   let catalog = DeviceProfileCatalog.shared.profile(id: templateID),
                   catalog.category == .powerbank {
                    assignedProfileID = templateID
                } else {
                    assignedProfileID = "generic-powerbank"
                }
                setValue(assignedProfileID, on: powerbank, key: "profileID")
                setValue(now, on: powerbank, key: "updatedAt")
                didChange = true
            }

            if didChange {
                didSave = saveContext()
            } else {
                didSave = true // nothing to do counts as success
            }
        }
        return didSave
    }

    private func promoteLegacyPowerbankDevice(_ device: NSManagedObject, now: Date) {
        let legacyID = stringValue(device, key: "id")
        let powerbank = NSEntityDescription.insertNewObject(
            forEntityName: EntityName.powerbank,
            into: context
        )
        setValue(legacyID ?? UUID().uuidString, on: powerbank, key: "id")
        setValue(stringValue(device, key: "name"), on: powerbank, key: "name")
        setValue(stringValue(device, key: "qrIdentifier"), on: powerbank, key: "qrIdentifier")
        setValue(stringValue(device, key: "notes"), on: powerbank, key: "notes")
        setValue("none", on: powerbank, key: "batteryLevelReportingRawValue")
        setValue(Int16(0), on: powerbank, key: "batteryBarsCount")
        setValue(optionalDoubleValue(device, key: "estimatedBatteryCapacityWh") ?? 0, on: powerbank, key: "estimatedBatteryCapacityWh")
        setValue(optionalDoubleValue(device, key: "minimumCurrentAmps") ?? 0, on: powerbank, key: "minimumCurrentAmps")
        setValue("generic-powerbank", on: powerbank, key: "profileID")
        setValue(stringValue(device, key: "deviceTemplateID"), on: powerbank, key: "deviceTemplateID")
        setValue(dateValue(device, key: "createdAt") ?? now, on: powerbank, key: "createdAt")
        setValue(now, on: powerbank, key: "updatedAt")

        track("ChargeInsightsStore: promoted legacy class-.powerbank ChargedDevice (\(legacyID ?? "?")) to Powerbank entity")
        context.delete(device)
    }

    private func resolveProfileIDForLegacyDevice(_ device: NSManagedObject, now: Date) -> String {
        // 1. Direct catalog match by template ID (apple-iphone, apple-watch, etc.).
        if let templateID = stringValue(device, key: "deviceTemplateID"),
           DeviceProfileCatalog.shared.profile(id: templateID) != nil {
            return templateID
        }

        // 2. For chargers, map chargerType to a catalog charger profile.
        if stringValue(device, key: "deviceClassRawValue") == ChargedDeviceClass.charger.rawValue {
            if let chargerTypeRaw = stringValue(device, key: "chargerTypeRawValue"),
               let chargerType = ChargerType(rawValue: chargerTypeRaw) {
                switch chargerType {
                case .appleMagSafe: return "apple-magsafe-charger"
                case .appleWatch: return "apple-watch-charger"
                case .genericMagSafe: return "generic-magsafe-charger"
                case .genericQi: return "generic-qi-charger"
                }
            }
            return "generic-qi-charger"
        }

        // 3. Synthesize a custom DeviceProfile row matching the device's persisted state.
        return synthesizeCustomProfile(from: device, now: now)
    }

    private func synthesizeCustomProfile(from device: NSManagedObject, now: Date) -> String {
        let id = UUID().uuidString
        let deviceName = stringValue(device, key: "name") ?? "Untitled"
        let profileName = "\(deviceName) profile"

        let classRaw = stringValue(device, key: "deviceClassRawValue") ?? ChargedDeviceClass.other.rawValue
        let deviceClass = ChargedDeviceClass(rawValue: classRaw) ?? .other
        let category = ProfileCategory.fromLegacyDeviceClass(deviceClass)

        let supportsWired = (device.value(forKey: "supportsWiredCharging") as? Bool) ?? false
        let supportsWireless = (device.value(forKey: "supportsWirelessCharging") as? Bool) ?? false
        let chargingStateRaw = stringValue(device, key: "chargingStateAvailabilityRawValue") ?? ChargingStateAvailability.onOrOff.rawValue
        let chargingState = ChargingStateAvailability(rawValue: chargingStateRaw) ?? .onOrOff
        let wirelessProfileRaw = stringValue(device, key: "wirelessChargingProfileRawValue") ?? WirelessChargingProfile.genericQi.rawValue
        let wirelessProfile = WirelessChargingProfile(rawValue: wirelessProfileRaw) ?? .genericQi

        let allowedWirelessProfiles = supportsWireless ? [wirelessProfile] : []

        let profile = NSEntityDescription.insertNewObject(
            forEntityName: EntityName.deviceProfile,
            into: context
        )
        setValue(id, on: profile, key: "id")
        setValue(profileName, on: profile, key: "name")
        setValue(category.rawValue, on: profile, key: "categoryRawValue")
        setValue(category.symbolName, on: profile, key: "iconSymbolName")
        setValue(true, on: profile, key: "isCustom")
        setValue(Int16(1), on: profile, key: "schemaVersion")
        setValue(Int32(1000), on: profile, key: "sortOrder")
        setValue("Custom", on: profile, key: "group")
        setValue(supportsWired, on: profile, key: "capWiredCharging")
        setValue(supportsWireless, on: profile, key: "capWirelessCharging")
        setValue(allowedWirelessProfiles.map { $0.rawValue }.joined(separator: ","), on: profile, key: "capWirelessProfilesRawValue")
        setValue(chargingState.rawValue, on: profile, key: "capChargingStateAvailabilityRawValue")
        setValue(false, on: profile, key: "capHasInternalSubject")
        setValue(supportsWireless ? wirelessProfile.rawValue : nil, on: profile, key: "defaultWirelessChargingProfileRawValue")
        setValue(now, on: profile, key: "createdAt")
        setValue(now, on: profile, key: "updatedAt")

        track("ChargeInsightsStore: synthesized custom DeviceProfile \(id) for legacy device \(stringValue(device, key: "id") ?? "?")")
        return id
    }

    private func applyCatalogProfile(
        _ profile: DeviceProfileDefinition,
        to object: NSManagedObject,
        updatedAt: Date
    ) {
        setValue(profile.name, on: object, key: "name")
        setValue(profile.category.rawValue, on: object, key: "categoryRawValue")
        setValue(profile.icon.name, on: object, key: "iconSymbolName")
        setValue(profile.icon.fallbackSystemName, on: object, key: "iconFallbackSymbolName")
        setValue(false, on: object, key: "isCustom")
        setValue(Int16(1), on: object, key: "schemaVersion")
        setValue(Int32(profile.sortOrder), on: object, key: "sortOrder")
        setValue(profile.group, on: object, key: "group")
        setValue(profile.capWiredCharging, on: object, key: "capWiredCharging")
        setValue(profile.capWirelessCharging, on: object, key: "capWirelessCharging")
        setValue(profile.wirelessProfilesCSV, on: object, key: "capWirelessProfilesRawValue")
        setValue(profile.capChargingStateAvailability.rawValue, on: object, key: "capChargingStateAvailabilityRawValue")
        setValue(profile.capHasInternalSubject, on: object, key: "capHasInternalSubject")
        setValue(profile.defaultWirelessChargingProfile?.rawValue, on: object, key: "defaultWirelessChargingProfileRawValue")
        setValue(profile.defaultWiredMinimumCurrentAmps ?? 0, on: object, key: "defaultWiredMinimumCurrentAmps")
        setValue(profile.defaultWirelessMinimumCurrentAmps ?? 0, on: object, key: "defaultWirelessMinimumCurrentAmps")
        setValue(profile.defaultWiredEstimatedBatteryCapacityWh ?? 0, on: object, key: "defaultWiredEstimatedBatteryCapacityWh")
        setValue(profile.defaultWirelessEstimatedBatteryCapacityWh ?? 0, on: object, key: "defaultWirelessEstimatedBatteryCapacityWh")
        setValue(updatedAt, on: object, key: "updatedAt")
    }

    @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
    }

    // Heals the invariant "at most one open session per meter MAC".
    // Called after every remote CloudKit sync import to resolve sessions that were started
    // independently on different devices while offline.
    //
    // Scenario: session A started on Device 1 and forgotten; user starts session B on Device 2
    // while offline. After sync both appear open for the same meter.
    //
    // Winner = session with the latest startedAt (represents the user's intentional new session).
    // Loser endedAt is set to winner's startedAt so there is no time overlap.
    @discardableResult
    func healDuplicateOpenSessions() -> Bool {
        var didSave = false

        context.performAndWait {
            let openSessions = fetchOpenSessionObjects()

            var sessionsByMAC: [String: [NSManagedObject]] = [:]
            for session in openSessions {
                guard let mac = stringValue(session, key: "meterMACAddress") else { continue }
                sessionsByMAC[mac, default: []].append(session)
            }

            let duplicatedMACs = sessionsByMAC.filter { $0.value.count > 1 }
            guard !duplicatedMACs.isEmpty else { return }

            var chargedDeviceIDsToRefresh = Set<String>()

            for (_, sessions) in duplicatedMACs {
                // Winner = most recently started (explicit user intent); tie-break by measuredEnergyWh
                let winner = sessions.max { a, b in
                    let aDate = (a.value(forKey: "startedAt") as? Date) ?? .distantPast
                    let bDate = (b.value(forKey: "startedAt") as? Date) ?? .distantPast
                    if aDate != bDate { return aDate < bDate }
                    let aEnergy = (a.value(forKey: "measuredEnergyWh") as? Double) ?? 0
                    let bEnergy = (b.value(forKey: "measuredEnergyWh") as? Double) ?? 0
                    return aEnergy < bEnergy
                }
                let winnerStartedAt = (winner?.value(forKey: "startedAt") as? Date) ?? Date()

                for loser in sessions where loser !== winner {
                    // End the loser exactly when the winner began — no overlap.
                    finishSession(loser, observedAt: winnerStartedAt, finalBatteryPercent: nil, status: .abandoned)
                    loser.setValue(true, forKey: "wasConflictHealed")
                    if let chargedDeviceID = stringValue(loser, key: "chargedDeviceID") {
                        chargedDeviceIDsToRefresh.insert(chargedDeviceID)
                    }
                    track("ChargeInsightsStore: healed duplicate open session \(stringValue(loser, key: "id") ?? "?") for meter \(stringValue(loser, key: "meterMACAddress") ?? "?")")
                }
            }

            guard saveContext() else { return }

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

        return didSave
    }

    @discardableResult
    func createDevice(
        name: String,
        deviceClass: ChargedDeviceClass,
        templateID: String?,
        profileID: String? = nil,
        hasInternalSubject: Bool = false,
        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)
        let normalizedProfileID = normalizedOptionalText(profileID)
        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(normalizedProfileID, forKey: "profileID")
            object.setValue(hasInternalSubject, forKey: "hasInternalSubject")
            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(now, forKey: "createdAt")
            object.setValue(now, forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func createPowerbank(
        name: String,
        templateID: String?,
        batteryLevelReporting: BatteryLevelReporting,
        batteryBarsCount: Int,
        notes: String?
    ) -> Bool {
        let normalizedName = normalizedText(name)
        guard !normalizedName.isEmpty else { return false }

        var didSave = false
        context.performAndWait {
            guard let entity = NSEntityDescription.entity(forEntityName: EntityName.powerbank, 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(generateQRIdentifier(), forKey: "qrIdentifier")
            object.setValue(normalizedTemplateID(templateID, kind: .device), forKey: "deviceTemplateID")
            object.setValue(batteryLevelReporting.rawValue, forKey: "batteryLevelReportingRawValue")
            object.setValue(Int16(batteryLevelReporting == .bars ? max(1, batteryBarsCount) : 0), forKey: "batteryBarsCount")
            object.setValue(normalizedOptionalText(notes), forKey: "notes")
            object.setValue(now, forKey: "createdAt")
            object.setValue(now, forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func updatePowerbank(
        id: UUID,
        name: String,
        templateID: String?,
        batteryLevelReporting: BatteryLevelReporting,
        batteryBarsCount: Int,
        notes: String?
    ) -> Bool {
        let normalizedName = normalizedText(name)
        guard !normalizedName.isEmpty else { return false }

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

            let now = Date()
            object.setValue(normalizedName, forKey: "name")
            object.setValue(normalizedTemplateID(templateID, kind: .device), forKey: "deviceTemplateID")
            object.setValue(batteryLevelReporting.rawValue, forKey: "batteryLevelReportingRawValue")
            object.setValue(Int16(batteryLevelReporting == .bars ? max(1, batteryBarsCount) : 0), forKey: "batteryBarsCount")
            object.setValue(normalizedOptionalText(notes), forKey: "notes")
            object.setValue(now, forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

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

        context.performAndWait {
            guard let powerbank = fetchPowerbankObject(id: powerbankID.uuidString) else {
                return
            }

            // Detach references from any session that mentions this powerbank as subject or source.
            let subjectSessions = fetchSessions(forPowerbankSubjectID: powerbankID.uuidString)
            for session in subjectSessions {
                if let sessionID = stringValue(session, key: "id") {
                    fetchCheckpointObjects(forSessionID: sessionID).forEach(context.delete)
                    fetchSessionSampleObjects(forSessionID: sessionID).forEach(context.delete)
                }
                context.delete(session)
            }

            let sourceSessions = fetchSessions(forPowerbankSourceID: powerbankID.uuidString)
            for session in sourceSessions {
                session.setValue(nil, forKey: "sourcePowerbankID")
                session.setValue(Date(), forKey: "updatedAt")
            }

            context.delete(powerbank)
            didSave = saveContext()
        }

        return didSave
    }

    func createCharger(
        name: String,
        chargerType: ChargerType,
        notes: 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(now, forKey: "createdAt")
            object.setValue(now, forKey: "updatedAt")
            didSave = saveContext()
        }
        return didSave
    }

    @discardableResult
    func updateDevice(
        id: UUID,
        name: String,
        deviceClass: ChargedDeviceClass,
        templateID: String?,
        profileID: String? = nil,
        hasInternalSubject: Bool = false,
        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)
        let normalizedProfileID = normalizedOptionalText(profileID)
        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(normalizedProfileID, forKey: "profileID")
            object.setValue(hasInternalSubject, forKey: "hasInternalSubject")
            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 startSession(
        for snapshot: ChargingMonitorSnapshot,
        chargedDeviceID: UUID,
        chargerID: UUID?,
        sourcePowerbankID: UUID? = nil,
        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
            }
            let powerbankSource = sourcePowerbankID.flatMap { fetchPowerbankObject(id: $0.uuidString) }
            // Wireless transport historically required a charger; accept a powerbank in its place.
            guard resolvedChargingTransportMode == .wired || charger != nil || powerbankSource != 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 let powerbankSource, let powerbankIDString = stringValue(powerbankSource, key: "id") {
                session.setValue(powerbankIDString, forKey: "sourcePowerbankID")
            }

            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
            }

            restoreMeasuredTotalsFromLatestSampleIfNeeded(session)

            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
    ) -> 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,
                flag: .intermediate,
                to: session
            )
        }
        return didSave
    }

    @discardableResult
    func addBatteryCheckpoint(
        percent: Double,
        for sessionID: UUID,
        measuredEnergyWh: Double? = nil,
        subject: CheckpointSubject = .chargedDevice,
        barsValue: Int = 0
    ) -> 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,
                flag: .intermediate,
                subject: subject,
                barsValue: barsValue,
                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 commitSessionTrim(sessionID: UUID) -> Bool {
        var didSave = false
        context.performAndWait {
            guard let session = fetchSessionObject(id: sessionID.uuidString),
                  statusValue(session, key: "statusRawValue")?.isOpen == false else {
                return
            }

            guard dateValue(session, key: "trimStart") != nil
                    || dateValue(session, key: "trimEnd") != nil else {
                return
            }

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

            let effectiveStart = min(max(dateValue(session, key: "trimStart") ?? sessionStart, sessionStart), sessionEnd)
            let effectiveEnd = max(
                min(dateValue(session, key: "trimEnd") ?? sessionEnd, sessionEnd),
                effectiveStart
            )

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

            let baselineSample = allSamples.last { $0.timestamp <= effectiveStart }
            let endSample = allSamples.last { $0.timestamp <= effectiveEnd }
            let baselineEnergy = baselineSample?.energy ?? 0
            let baselineCharge = baselineSample?.charge ?? 0
            let committedEnergy = endSample.map { max($0.energy - baselineEnergy, 0) }
                ?? doubleValue(session, key: "measuredEnergyWh")
            let committedCharge = endSample.map { max($0.charge - baselineCharge, 0) }
                ?? doubleValue(session, key: "measuredChargeAh")

            var retainedSamples: [(current: Double, power: Double, voltage: Double?)] = []
            for sample in sampleObjects {
                guard let timestamp = dateValue(sample, key: "timestamp") else {
                    context.delete(sample)
                    continue
                }

                guard timestamp >= effectiveStart && timestamp <= effectiveEnd else {
                    context.delete(sample)
                    continue
                }

                let rebasedEnergy = max(doubleValue(sample, key: "measuredEnergyWh") - baselineEnergy, 0)
                let rebasedCharge = max(doubleValue(sample, key: "measuredChargeAh") - baselineCharge, 0)
                let elapsed = max(timestamp.timeIntervalSince(effectiveStart), 0)
                let rebasedBucketIndex = Int32(floor(elapsed / Self.aggregatedSampleBucketDuration))

                sample.setValue("\(sessionID.uuidString)-\(rebasedBucketIndex)", forKey: "id")
                sample.setValue(rebasedBucketIndex, forKey: "bucketIndex")
                sample.setValue(rebasedEnergy, forKey: "measuredEnergyWh")
                sample.setValue(rebasedCharge, forKey: "measuredChargeAh")
                sample.setValue(Date(), forKey: "updatedAt")

                retainedSamples.append(
                    (
                        current: doubleValue(sample, key: "averageCurrentAmps"),
                        power: doubleValue(sample, key: "averagePowerWatts"),
                        voltage: optionalDoubleValue(sample, key: "averageVoltageVolts")
                    )
                )
            }

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

                guard timestamp >= effectiveStart && timestamp <= effectiveEnd else {
                    context.delete(checkpoint)
                    continue
                }

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

            if !retainedSamples.isEmpty {
                let positiveCurrents = retainedSamples.map { $0.current }.filter { $0 > 0 }
                session.setValue(positiveCurrents.min(), forKey: "minimumObservedCurrentAmps")
                session.setValue(retainedSamples.map { $0.current }.max(), forKey: "maximumObservedCurrentAmps")
                session.setValue(retainedSamples.map { $0.power }.max(), forKey: "maximumObservedPowerWatts")
                session.setValue(retainedSamples.compactMap { $0.voltage }.max(), forKey: "maximumObservedVoltageVolts")
                session.setValue(
                    retainedSamples.contains { $0.power > 0.05 || $0.current > 0.01 },
                    forKey: "hasObservedChargeFlow"
                )
            } else {
                session.setValue(nil, forKey: "minimumObservedCurrentAmps")
                session.setValue(nil, forKey: "maximumObservedCurrentAmps")
                session.setValue(nil, forKey: "maximumObservedPowerWatts")
                session.setValue(nil, forKey: "maximumObservedVoltageVolts")
                session.setValue(committedEnergy > 0 || committedCharge > 0, forKey: "hasObservedChargeFlow")
            }

            session.setValue(effectiveStart, forKey: "startedAt")
            session.setValue(effectiveEnd, forKey: "lastObservedAt")
            if dateValue(session, key: "endedAt") != nil {
                session.setValue(effectiveEnd, forKey: "endedAt")
            }
            session.setValue(committedEnergy, forKey: "measuredEnergyWh")
            session.setValue(committedCharge, forKey: "measuredChargeAh")
            session.setValue(nil, forKey: "trimStart")
            session.setValue(nil, forKey: "trimEnd")
            session.setValue(Date(), forKey: "updatedAt")

            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,
                    profileID: stringValue(device, key: "profileID"),
                    hasInternalSubject: (device.value(forKey: "hasInternalSubject") as? Bool) ?? false,
                    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"),
                    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 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
    }

    /// Materialize all Powerbank entities into Swift summaries, with sessions in which the
    /// powerbank participates either as the charged subject (`chargedPowerbankID`) or as the
    /// supplying source (`sourcePowerbankID`). Discharge curve aggregation across multiple
    /// concurrent device-side sessions is derived view-side from `sessionsAsSource`.
    func fetchPowerbankSummaries() -> [PowerbankSummary] {
        var summaries: [PowerbankSummary] = []

        context.performAndWait {
            let powerbanks = fetchObjects(entityName: EntityName.powerbank)
            guard !powerbanks.isEmpty else {
                return
            }

            let sessions = fetchObjects(entityName: EntityName.chargeSession)
            let checkpoints = fetchObjects(entityName: EntityName.chargeCheckpoint)
            let checkpointsBySessionID = Dictionary(grouping: checkpoints) {
                stringValue($0, key: "sessionID") ?? ""
            }
            let sessionsAsSubject = Dictionary(grouping: sessions) {
                stringValue($0, key: "chargedPowerbankID") ?? ""
            }
            let sessionsAsSource = Dictionary(grouping: sessions) {
                stringValue($0, key: "sourcePowerbankID") ?? ""
            }

            summaries = powerbanks.compactMap { powerbank in
                guard
                    let id = uuidValue(powerbank, key: "id"),
                    let name = stringValue(powerbank, key: "name"),
                    let qrIdentifier = stringValue(powerbank, key: "qrIdentifier")
                else {
                    return nil
                }

                let templateID = stringValue(powerbank, key: "deviceTemplateID")
                let templateDefinition = ChargedDeviceTemplateCatalog.shared.template(id: templateID)

                let reportingRaw = stringValue(powerbank, key: "batteryLevelReportingRawValue")
                let reporting = reportingRaw.flatMap(BatteryLevelReporting.init(rawValue:)) ?? .percent
                let barsCount = Int(optionalInt16Value(powerbank, key: "batteryBarsCount") ?? 0)

                let sessionsAsSubjectRaw = sessionsAsSubject[id.uuidString] ?? []
                let sessionsAsSourceRaw = sessionsAsSource[id.uuidString] ?? []

                let subjectSessions = sessionsAsSubjectRaw
                    .compactMap { session -> ChargeSessionSummary? in
                        let sessionID = stringValue(session, key: "id") ?? ""
                        return makeSessionSummary(
                            from: session,
                            checkpoints: checkpointsBySessionID[sessionID] ?? [],
                            samples: []
                        )
                    }
                    .sorted { $0.startedAt > $1.startedAt }

                let sourceSessions = sessionsAsSourceRaw
                    .compactMap { session -> ChargeSessionSummary? in
                        let sessionID = stringValue(session, key: "id") ?? ""
                        return makeSessionSummary(
                            from: session,
                            checkpoints: checkpointsBySessionID[sessionID] ?? [],
                            samples: []
                        )
                    }
                    .sorted { $0.startedAt > $1.startedAt }

                let observedVoltages: [Double] = (stringValue(powerbank, key: "sourceObservedVoltageSelectionsRawValue") ?? "")
                    .split(separator: ",")
                    .compactMap { Double($0) }
                    .sorted()

                let derived = derivedPowerbankMetrics(
                    sessionsAsSubject: subjectSessions,
                    sessionsAsSource: sourceSessions,
                    reporting: reporting
                )

                return PowerbankSummary(
                    id: id,
                    qrIdentifier: qrIdentifier,
                    name: name,
                    deviceTemplateID: templateID,
                    templateDefinition: templateDefinition,
                    batteryLevelReporting: reporting,
                    batteryBarsCount: barsCount,
                    estimatedBatteryCapacityWh: optionalDoubleValue(powerbank, key: "estimatedBatteryCapacityWh"),
                    apparentCapacityWh: derived.apparentCapacityWh
                        ?? optionalDoubleValue(powerbank, key: "apparentCapacityWh"),
                    configuredCompletionCurrentAmps: optionalDoubleValue(powerbank, key: "configuredCompletionCurrentAmps"),
                    learnedCompletionCurrentAmps: optionalDoubleValue(powerbank, key: "learnedCompletionCurrentAmps"),
                    minimumCurrentAmps: optionalDoubleValue(powerbank, key: "minimumCurrentAmps"),
                    sourceObservedVoltageSelections: derived.voltageMaxCurrents.keys.sorted().isEmpty
                        ? observedVoltages
                        : derived.voltageMaxCurrents.keys.sorted(),
                    sourceVoltageMaxCurrents: derived.voltageMaxCurrents,
                    sourceIdleCurrentAmps: optionalDoubleValue(powerbank, key: "sourceIdleCurrentAmps"),
                    sourceMaximumPowerWatts: derived.maxPowerWatts
                        ?? optionalDoubleValue(powerbank, key: "sourceMaximumPowerWatts"),
                    sourceEfficiencyFactor: derived.efficiencyFactor
                        ?? optionalDoubleValue(powerbank, key: "sourceEfficiencyFactor"),
                    notes: stringValue(powerbank, key: "notes"),
                    createdAt: dateValue(powerbank, key: "createdAt") ?? Date(),
                    updatedAt: dateValue(powerbank, key: "updatedAt") ?? Date(),
                    sessionsAsSubject: subjectSessions,
                    sessionsAsSource: sourceSessions
                )
            }
        }

        return summaries
    }

    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")

        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")
        setValue(predictedBatteryPercent(for: session), on: sample, key: "estimatedBatteryPercent")
        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)
        refreshEstimatedBatteryPercents(for: session)
        session.setValue(observedAt, forKey: "updatedAt")

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

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

        let estimatedCapacityWh = resolvedEstimatedBatteryCapacityWh(
            for: session,
            chargedDevice: chargedDevice
        )
        let deviceClass = ChargedDeviceClass(rawValue: stringValue(chargedDevice, key: "deviceClassRawValue") ?? "") ?? .other
        let canUseCheckpointEnergyMap = deviceClass == .watch || deviceClass == .iphone
        let measuredEnergyWh = effectiveEnergyWhOverride
            ?? effectiveBatteryEnergyWh(
                rawMeasuredEnergyWh: doubleValue(session, key: "measuredEnergyWh"),
                for: session
            )
        let sessionID = stringValue(session, key: "id") ?? ""

        func anchorCapacityCandidates(from anchors: [BatteryLevelPredictionAnchor]) -> [Double] {
            var candidates: [Double] = []

            for lowerIndex in anchors.indices {
                for upperIndex in anchors.indices where upperIndex > lowerIndex {
                    let lower = anchors[lowerIndex]
                    let upper = anchors[upperIndex]
                    let percentDelta = upper.percent - lower.percent
                    let energyDelta = upper.energyWh - lower.energyWh

                    guard percentDelta >= 3, energyDelta > 0.01 else {
                        continue
                    }

                    let capacityWh = energyDelta / (percentDelta / 100)
                    guard capacityWh.isFinite, capacityWh > 0, capacityWh < 1_000 else {
                        continue
                    }

                    candidates.append(capacityWh)
                }
            }

            return candidates
        }

        func inferredCheckpointEnergyMapCapacityWh(from anchors: [BatteryLevelPredictionAnchor]) -> Double? {
            let candidates = anchorCapacityCandidates(from: anchors)
            guard !candidates.isEmpty else {
                return nil
            }

            let sortedCandidates = candidates.sorted()
            return sortedCandidates[sortedCandidates.count / 2]
        }

        var anchors: [BatteryLevelPredictionAnchor] = []
        if let startBatteryPercent = optionalDoubleValue(session, key: "startBatteryPercent"),
           startBatteryPercent >= 0 {
            anchors.append(
                BatteryLevelPredictionAnchor(
                    percent: startBatteryPercent,
                    energyWh: 0,
                    timestamp: dateValue(session, key: "trimStart")
                        ?? dateValue(session, key: "startedAt")
                        ?? Date.distantPast,
                    description: "session start",
                    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 {
                BatteryLevelPredictionAnchor(
                    percent: $0.batteryPercent,
                    energyWh: $0.measuredEnergyWh,
                    timestamp: $0.timestamp,
                    description: $0.flag.anchorDescription,
                    isCheckpoint: true
                )
            }
        anchors.append(contentsOf: checkpointAnchors)

        if optionalDoubleValue(session, key: "startBatteryPercent") == unresolvedFlatBatteryPercent {
            if let virtualZeroEnergyWh = BatteryLevelPredictionTuning.inferredVirtualZeroEnergyWh(
                from: anchors,
                estimatedCapacityWh: estimatedCapacityWh,
                historicalReserveEnergyWh: estimatedFlatReserveEnergyWh(
                    forChargedDeviceID: chargedDeviceID,
                    excludingSessionID: sessionID
                )
            ) {
                anchors.append(
                    BatteryLevelPredictionAnchor(
                        percent: 0,
                        energyWh: virtualZeroEnergyWh,
                        timestamp: dateValue(session, key: "trimStart")
                            ?? dateValue(session, key: "startedAt")
                            ?? Date.distantPast,
                        description: "estimated flat reserve",
                        isCheckpoint: false
                    )
                )
            } else if let firstCheckpoint = anchors.min(by: { $0.energyWh < $1.energyWh }),
                      measuredEnergyWh < firstCheckpoint.energyWh - 0.05 {
                return nil
            }
        }

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

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

        let inferredCapacityWh = estimatedCapacityWh
            ?? (canUseCheckpointEnergyMap ? inferredCheckpointEnergyMapCapacityWh(from: sortedAnchors) : nil)
        let lowerAnchor = sortedAnchors.last { $0.energyWh <= measuredEnergyWh + 0.05 }
        let upperAnchor = sortedAnchors.first { $0.energyWh > measuredEnergyWh + 0.05 }
        let anchor = lowerAnchor ?? upperAnchor ?? sortedAnchors.first!

        if let lowerAnchor,
           let upperAnchor,
           upperAnchor.energyWh > lowerAnchor.energyWh + 0.05 {
            let interpolationProgress = min(
                max(
                    (measuredEnergyWh - lowerAnchor.energyWh) /
                    (upperAnchor.energyWh - lowerAnchor.energyWh),
                    0
                ),
                1
            )
            return min(
                max(
                    lowerAnchor.percent +
                    (upperAnchor.percent - lowerAnchor.percent) * interpolationProgress,
                    0
                ),
                100
            )
        }

        if let chargeCurve = typicalChargeCurve(
            forChargedDeviceID: chargedDeviceID,
            excludingSessionID: sessionID
        ),
           let curvePredictedPercent = BatteryLevelPredictionTuning.predictedPercent(
            anchorPercent: anchor.percent,
            anchorEnergyWh: anchor.energyWh,
            effectiveEnergyWh: measuredEnergyWh,
            chargeCurve: chargeCurve,
            deviationFactor: BatteryLevelPredictionTuning.deviationFactor(
                anchors: sortedAnchors,
                chargeCurve: chargeCurve
            )
           ) {
            return curvePredictedPercent
        }

        guard let inferredCapacityWh, inferredCapacityWh > 0 else {
            return nil
        }

        return BatteryLevelPredictionTuning.predictedPercent(
            anchorPercent: anchor.percent,
            anchorEnergyWh: anchor.energyWh,
            anchorTimestamp: anchor.timestamp,
            anchorIsCheckpoint: anchor.isCheckpoint,
            effectiveEnergyWh: measuredEnergyWh,
            referenceTimestamp: referenceTimestamp
                ?? dateValue(session, key: "lastObservedAt")
                ?? anchor.timestamp,
            estimatedCapacityWh: inferredCapacityWh
        )
    }

    private func effectiveBatteryEnergyWh(
        rawMeasuredEnergyWh: Double,
        for session: NSManagedObject
    ) -> Double {
        switch chargingTransportMode(for: session) {
        case .wired:
            return rawMeasuredEnergyWh
        case .wireless:
            if let factor = optionalDoubleValue(session, key: "wirelessEfficiencyFactor"), factor > 0 {
                return rawMeasuredEnergyWh * factor
            }
            let sessionMeasuredEnergyWh = doubleValue(session, key: "measuredEnergyWh")
            if let sessionEffectiveEnergyWh = optionalDoubleValue(session, key: "effectiveBatteryEnergyWh"),
               sessionMeasuredEnergyWh > 0 {
                return rawMeasuredEnergyWh * (sessionEffectiveEnergyWh / sessionMeasuredEnergyWh)
            }
            return rawMeasuredEnergyWh
        }
    }

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

        for sample in fetchSessionSampleObjects(forSessionID: sessionID) {
            let effectiveEnergyWh = effectiveBatteryEnergyWh(
                rawMeasuredEnergyWh: doubleValue(sample, key: "measuredEnergyWh"),
                for: session
            )
            let percent = predictedBatteryPercent(
                for: session,
                effectiveEnergyWhOverride: effectiveEnergyWh,
                referenceTimestamp: dateValue(sample, key: "timestamp")
            )
            setValue(percent, on: sample, key: "estimatedBatteryPercent")
            setValue(Date(), on: sample, key: "updatedAt")
        }
    }

    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,
        subject: CheckpointSubject = .chargedDevice,
        barsValue: Int = 0,
        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")
        checkpoint.setValue(UUID().uuidString, forKey: "id")
        checkpoint.setValue(sessionID, forKey: "sessionID")
        switch subject {
        case .chargedDevice:
            checkpoint.setValue(chargedDeviceID, forKey: "chargedDeviceID")
            checkpoint.setValue(nil, forKey: "powerbankID")
        case .powerbank:
            // Powerbank-side checkpoint: link to the powerbank source instead. ChargedDeviceID
            // stays nil so device capacity learning ignores it; the session backref is via sessionID.
            let powerbankID = stringValue(session, key: "sourcePowerbankID")
            checkpoint.setValue(nil, forKey: "chargedDeviceID")
            checkpoint.setValue(powerbankID, forKey: "powerbankID")
        }
        checkpoint.setValue(Int16(max(0, barsValue)), forKey: "batteryBarsValue")
        checkpoint.setValue(timestamp, forKey: "timestamp")
        checkpoint.setValue(percent, forKey: "batteryPercent")
        checkpoint.setValue(checkpointEnergyWh, forKey: "measuredEnergyWh")
        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")

        // Session start/end battery percent fields track the device subject only.
        if subject == .chargedDevice {
            let existingStartBatteryPercent = optionalDoubleValue(session, key: "startBatteryPercent")
            if existingStartBatteryPercent == nil {
                session.setValue(percent, forKey: "startBatteryPercent")
            }
            if (existingStartBatteryPercent ?? 0) >= 0 || percent > 0 {
                session.setValue(percent, forKey: "endBatteryPercent")
            }
        }
        session.setValue(timestamp, forKey: "updatedAt")
        updateCapacityEstimate(for: session)
        refreshEstimatedBatteryPercents(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)
        refreshEstimatedBatteryPercents(for: session)
    }

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

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

        guard saveContext() else {
            return false
        }

        // Device-subject checkpoints feed device-side capacity learning. Powerbank-subject
        // checkpoints feed powerbank-side derivation, which is computed at materialization time
        // (see PowerbankSummary fetch path).
        if subject == .chargedDevice {
            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 typicalChargeCurve(
        forChargedDeviceID chargedDeviceID: String,
        excludingSessionID excludedSessionID: String? = nil
    ) -> BatteryChargeCurve? {
        let sessionObjects = fetchSessions(forChargedDeviceID: chargedDeviceID)
            .filter {
                statusValue($0, key: "statusRawValue") == .completed
            }

        let sessionSummaries = sessionObjects.compactMap { session -> ChargeSessionSummary? in
            guard let sessionID = stringValue(session, key: "id"),
                  sessionID != excludedSessionID else {
                return nil
            }

            return makeSessionSummary(
                from: session,
                checkpoints: fetchCheckpointObjects(forSessionID: sessionID),
                samples: []
            )
        }

        return BatteryChargeCurve(
            typicalCurvePoints: buildTypicalCurve(from: sessionSummaries)
        )
    }

    private func estimatedFlatReserveEnergyWh(
        forChargedDeviceID chargedDeviceID: String,
        excludingSessionID excludedSessionID: String? = nil
    ) -> Double? {
        let reserves = fetchSessions(forChargedDeviceID: chargedDeviceID)
            .filter {
                statusValue($0, key: "statusRawValue") == .completed
                    && optionalDoubleValue($0, key: "startBatteryPercent") == unresolvedFlatBatteryPercent
                    && stringValue($0, key: "id") != excludedSessionID
            }
            .compactMap { session -> Double? in
                guard let sessionID = stringValue(session, key: "id") else {
                    return nil
                }

                let anchors = fetchCheckpointObjects(forSessionID: sessionID)
                    .compactMap(makeCheckpointSummary(from:))
                    .map {
                        BatteryLevelPredictionAnchor(
                            percent: $0.batteryPercent,
                            energyWh: $0.measuredEnergyWh,
                            timestamp: $0.timestamp,
                            description: $0.flag.anchorDescription,
                            isCheckpoint: true
                        )
                    }

                return BatteryLevelPredictionTuning.inferredVirtualZeroEnergyWh(
                    from: anchors,
                    estimatedCapacityWh: optionalDoubleValue(session, key: "capacityEstimateWh")
                )
            }

        guard !reserves.isEmpty else {
            return nil
        }

        let sortedReserves = reserves.sorted()
        return sortedReserves[sortedReserves.count / 2]
    }

    private func buildTypicalCurve(from sessions: [ChargeSessionSummary]) -> [TypicalChargeCurvePoint] {
        var groupedEnergyByBin: [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 energyWh = interpolatedTypicalCurvePoint(
                    for: Double(percentBin),
                    anchors: anchors
                ) else {
                    continue
                }

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

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

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

        var runningMaximumEnergyWh = 0.0

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

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

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

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

        if let startBatteryPercent = session.startBatteryPercent,
           startBatteryPercent.isFinite,
           startBatteryPercent >= 0,
           startBatteryPercent <= 100 {
            anchors.append(
                Anchor(
                    percent: startBatteryPercent,
                    energyWh: 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,
                    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)] = []

        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)
                )
            } else {
                collapsedAnchors.append(
                    (percent: anchor.percent, energyWh: anchor.energyWh)
                )
            }
        }

        var runningMaximumEnergyWh = 0.0

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

    private func interpolatedTypicalCurvePoint(
        for percent: Double,
        anchors: [(percent: Double, energyWh: Double)]
    ) -> 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 exactAnchor.energyWh
        }

        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
        return lowerAnchor.energyWh + ((upperAnchor.energyWh - lowerAnchor.energyWh) * ratio)
    }

    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,
            chargedPowerbankID: uuidValue(object, key: "chargedPowerbankID"),
            chargerID: uuidValue(object, key: "chargerID"),
            sourcePowerbankID: uuidValue(object, key: "sourcePowerbankID"),
            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"),
            meterEnergyBaselineWh: optionalDoubleValue(object, key: "meterEnergyBaselineWh"),
            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"),
            wasConflictHealed: boolValue(object, key: "wasConflictHealed"),
            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,
            powerbankID: uuidValue(object, key: "powerbankID"),
            batteryBarsValue: Int(optionalInt16Value(object, key: "batteryBarsValue") ?? 0),
            timestamp: timestamp,
            batteryPercent: doubleValue(object, key: "batteryPercent"),
            measuredEnergyWh: doubleValue(object, key: "measuredEnergyWh"),
            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"),
            estimatedBatteryPercent: optionalDoubleValue(object, key: "estimatedBatteryPercent"),
            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 fetchSessions(forPowerbankSubjectID powerbankID: String) -> [NSManagedObject] {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSession)
        request.predicate = NSPredicate(format: "chargedPowerbankID == %@", powerbankID)
        request.sortDescriptors = [NSSortDescriptor(key: "startedAt", ascending: true)]
        return (try? context.fetch(request)) ?? []
    }

    private func fetchSessions(forPowerbankSourceID powerbankID: String) -> [NSManagedObject] {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.chargeSession)
        request.predicate = NSPredicate(format: "sourcePowerbankID == %@", powerbankID)
        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 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 fetchPowerbankObject(id: String) -> NSManagedObject? {
        let request = NSFetchRequest<NSManagedObject>(entityName: EntityName.powerbank)
        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
    }

    /// Resolves the active DeviceProfile for a ChargedDevice — catalog first
    /// (covers all built-in templates and chargers), then DB-backed custom profiles.
    /// Returns nil only for devices that escaped migration (shouldn't happen post Phase 3).
    private func resolvedProfileDefinition(for chargedDevice: NSManagedObject) -> DeviceProfileDefinition? {
        if let profileID = stringValue(chargedDevice, key: "profileID") {
            if let catalogProfile = DeviceProfileCatalog.shared.profile(id: profileID) {
                return catalogProfile
            }
            if let stored = fetchDeviceProfileObject(id: profileID),
               let definition = makeProfileDefinition(from: stored) {
                return definition
            }
        }
        // Pre-migration fallback: try the legacy template ID against the catalog.
        if let templateID = stringValue(chargedDevice, key: "deviceTemplateID"),
           let catalogProfile = DeviceProfileCatalog.shared.profile(id: templateID) {
            return catalogProfile
        }
        return nil
    }

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

    private func makeProfileDefinition(from object: NSManagedObject) -> DeviceProfileDefinition? {
        guard let id = stringValue(object, key: "id"),
              let categoryRaw = stringValue(object, key: "categoryRawValue"),
              let category = ProfileCategory(rawValue: categoryRaw) else {
            return nil
        }
        let name = stringValue(object, key: "name") ?? id
        let group = stringValue(object, key: "group") ?? "Custom"
        let iconName = stringValue(object, key: "iconSymbolName") ?? category.symbolName
        let iconFallback = stringValue(object, key: "iconFallbackSymbolName")
        let icon = ChargedDeviceTemplateIcon(type: .systemSymbol, name: iconName, fallbackSystemName: iconFallback)
        let stateRaw = stringValue(object, key: "capChargingStateAvailabilityRawValue")
            ?? ChargingStateAvailability.onOrOff.rawValue
        let stateAvailability = ChargingStateAvailability(rawValue: stateRaw) ?? .onOrOff
        let allowedWirelessProfiles = DeviceProfileDefinition.decodeWirelessProfilesCSV(
            stringValue(object, key: "capWirelessProfilesRawValue")
        )
        let defaultWirelessProfileRaw = stringValue(object, key: "defaultWirelessChargingProfileRawValue")
        let defaultWirelessProfile = defaultWirelessProfileRaw.flatMap(WirelessChargingProfile.init(rawValue:))

        return DeviceProfileDefinition(
            id: id,
            name: name,
            group: group,
            category: category,
            icon: icon,
            sortOrder: Int((object.value(forKey: "sortOrder") as? Int32) ?? 1000),
            capWiredCharging: (object.value(forKey: "capWiredCharging") as? Bool) ?? false,
            capWirelessCharging: (object.value(forKey: "capWirelessCharging") as? Bool) ?? false,
            capWirelessProfiles: allowedWirelessProfiles,
            capChargingStateAvailability: stateAvailability,
            capHasInternalSubject: (object.value(forKey: "capHasInternalSubject") as? Bool) ?? false,
            defaultWirelessChargingProfile: defaultWirelessProfile,
            defaultWiredMinimumCurrentAmps: optionalDoubleValue(object, key: "defaultWiredMinimumCurrentAmps"),
            defaultWirelessMinimumCurrentAmps: optionalDoubleValue(object, key: "defaultWirelessMinimumCurrentAmps"),
            defaultWiredEstimatedBatteryCapacityWh: optionalDoubleValue(object, key: "defaultWiredEstimatedBatteryCapacityWh"),
            defaultWirelessEstimatedBatteryCapacityWh: optionalDoubleValue(object, key: "defaultWirelessEstimatedBatteryCapacityWh")
        )
    }

    /// Synthesises a `ChargedDeviceTemplateDefinition` from the active profile so the
    /// existing UI surfaces (icons, group titles, capability summaries) keep working
    /// without forking. Catalog profiles return their canonical template; custom
    /// profiles return a definition derived from the profile's persisted shape.
    private func templateDefinition(for chargedDevice: NSManagedObject) -> ChargedDeviceTemplateDefinition? {
        guard let profile = resolvedProfileDefinition(for: chargedDevice) else { return nil }

        let kind = profile.category.kind
        // Pick a representative wireless profile for the legacy template shape.
        let wirelessProfile = profile.defaultWirelessChargingProfile
            ?? profile.capWirelessProfiles.first
            ?? .genericQi

        return ChargedDeviceTemplateDefinition(
            id: profile.id,
            name: profile.name,
            group: profile.group,
            kind: kind,
            deviceClass: legacyClass(for: profile.category),
            icon: profile.icon,
            chargingStateAvailability: profile.capChargingStateAvailability,
            supportsWiredCharging: profile.capWiredCharging,
            supportsWirelessCharging: profile.capWirelessCharging,
            wirelessChargingProfile: wirelessProfile,
            sortOrder: profile.sortOrder
        )
    }

    private func legacyClass(for category: ProfileCategory) -> ChargedDeviceClass {
        switch category {
        case .phone: return .iphone
        case .watch: return .watch
        case .powerbank: return .powerbank
        case .charger: return .charger
        case .tablet, .laptop, .audioAccessory, .accessoryCase, .other: return .other
        }
    }

    private func supportsWiredCharging(for chargedDevice: NSManagedObject) -> Bool {
        let persistedWiredCharging = chargedDevice.value(forKey: "supportsWiredCharging") == nil
            ? true
            : boolValue(chargedDevice, key: "supportsWiredCharging")

        if let profile = resolvedProfileDefinition(for: chargedDevice) {
            // Profile capability is the upper bound; user opt-out preserved.
            return persistedWiredCharging && profile.capWiredCharging
        }

        // Pre-migration fallback: legacy class enforcement.
        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 persistedWirelessCharging = chargedDevice.value(forKey: "supportsWirelessCharging") == nil
            ? false
            : boolValue(chargedDevice, key: "supportsWirelessCharging")

        if let profile = resolvedProfileDefinition(for: chargedDevice) {
            return persistedWirelessCharging && profile.capWirelessCharging
        }

        let persistedWiredCharging = chargedDevice.value(forKey: "supportsWiredCharging") == nil
            ? true
            : boolValue(chargedDevice, key: "supportsWiredCharging")
        return deviceClass(for: chargedDevice).normalizedChargingSupport(
            supportsWiredCharging: persistedWiredCharging,
            supportsWirelessCharging: persistedWirelessCharging
        ).wireless
    }

    private func chargingStateAvailability(for chargedDevice: NSManagedObject) -> ChargingStateAvailability {
        if let profile = resolvedProfileDefinition(for: chargedDevice) {
            return profile.capChargingStateAvailability
        }

        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
        }
        let persisted = stringValue(chargedDevice, key: "wirelessChargingProfileRawValue")
            .flatMap(WirelessChargingProfile.init(rawValue:))

        if let profile = resolvedProfileDefinition(for: chargedDevice),
           !profile.capWirelessProfiles.isEmpty {
            // Persisted wins iff still allowed by capabilities; else fall back to profile default.
            if let persisted, profile.capWirelessProfiles.contains(persisted) {
                return persisted
            }
            return profile.defaultWirelessChargingProfile
                ?? profile.capWirelessProfiles.first
                ?? .genericQi
        }

        return persisted ?? .genericQi
    }

    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 {
        if 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 {
            return true
        }

        guard let sessionID = stringValue(session, key: "id") else {
            return false
        }

        return fetchSessionSampleObjects(forSessionID: sessionID).contains { sample in
            doubleValue(sample, key: "measuredEnergyWh") > 0
                || doubleValue(sample, key: "measuredChargeAh") > 0
                || (optionalDoubleValue(sample, key: "averageCurrentAmps") ?? 0) > 0
                || (optionalDoubleValue(sample, key: "averagePowerWatts") ?? 0) > 0
        }
    }

    private func restoreMeasuredTotalsFromLatestSampleIfNeeded(_ session: NSManagedObject) {
        guard let sessionID = stringValue(session, key: "id"),
              let latestSample = fetchSessionSampleObjects(forSessionID: sessionID).max(by: {
                  (dateValue($0, key: "timestamp") ?? .distantPast) < (dateValue($1, key: "timestamp") ?? .distantPast)
              }) else {
            return
        }

        let sampleEnergyWh = doubleValue(latestSample, key: "measuredEnergyWh")
        if doubleValue(session, key: "measuredEnergyWh") <= 0, sampleEnergyWh > 0 {
            session.setValue(sampleEnergyWh, forKey: "measuredEnergyWh")
        }

        let sampleChargeAh = doubleValue(latestSample, key: "measuredChargeAh")
        if doubleValue(session, key: "measuredChargeAh") <= 0, sampleChargeAh > 0 {
            session.setValue(sampleChargeAh, forKey: "measuredChargeAh")
        }
    }

    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()
    }

    /// View-time derivation of powerbank metrics from materialized session summaries.
    /// Mirrors the charger derivation pattern but works on `ChargeSessionSummary` (already
    /// projected) so we don't need to re-fetch NSManagedObjects.
    /// - voltage profile: groups source-side sessions by selected voltage palier (rounded
    ///   to 0.5V) and tracks max current observed at each palier.
    /// - max power: max across source-side sessions' `maximumObservedPowerWatts`.
    /// - efficiency: ratio of total Wh delivered (as source) vs total Wh received (as subject).
    ///   Computed only when both sides have non-trivial energy logged.
    /// - apparent capacity: sum of source-side delivered Wh between the most recent two
    ///   powerbank-side checkpoints with sufficient battery percent delta. Best-effort.
    private func derivedPowerbankMetrics(
        sessionsAsSubject: [ChargeSessionSummary],
        sessionsAsSource: [ChargeSessionSummary],
        reporting: BatteryLevelReporting
    ) -> (
        voltageMaxCurrents: [Double: Double],
        maxPowerWatts: Double?,
        efficiencyFactor: Double?,
        apparentCapacityWh: Double?
    ) {
        var voltageMaxCurrents: [Double: Double] = [:]
        var maxPower: Double? = nil

        for session in sessionsAsSource {
            if let voltage = session.selectedSourceVoltageVolts, voltage > 0 {
                let palier = (voltage * 2).rounded() / 2  // 0.5V buckets
                if let maxCurrent = session.maximumObservedCurrentAmps, maxCurrent > 0 {
                    let prev = voltageMaxCurrents[palier] ?? 0
                    voltageMaxCurrents[palier] = max(prev, maxCurrent)
                }
            }
            if let power = session.maximumObservedPowerWatts, power > 0 {
                maxPower = max(maxPower ?? 0, power)
            }
        }

        let totalDelivered = sessionsAsSource.reduce(0.0) { $0 + $1.measuredEnergyWh }
        let totalReceived = sessionsAsSubject.reduce(0.0) { $0 + $1.measuredEnergyWh }
        let efficiency: Double? = (totalDelivered > 0.5 && totalReceived > 0.5)
            ? totalDelivered / totalReceived
            : nil

        // Apparent capacity heuristics depend on what reporting the powerbank supports:
        //
        // - `.fullOnly`: the only honest signal is the "full" anchor. We look for two
        //   consecutive full markers (one before a discharge cycle, one after the next
        //   recharge) and use the source-side energy delivered between them. Single-LED
        //   powerbanks naturally produce two 100% datapoints separated by usage.
        // - `.percent` / `.bars`: pair the most recent powerbank-side checkpoints with a
        //   meaningful battery delta (≥ 30%) and sum source-side energy in that window.
        // - `.none`: no powerbank checkpoints exist, so apparent capacity stays nil here
        //   and would have to be inferred differently (currently not attempted).
        var apparentCapacity: Double? = nil

        let powerbankCheckpoints = (sessionsAsSource + sessionsAsSubject)
            .flatMap { $0.checkpoints.filter { $0.subject == .powerbank } }
            .sorted { $0.timestamp < $1.timestamp }

        switch reporting {
        case .fullOnly:
            let fullMarkers = powerbankCheckpoints.filter { $0.batteryPercent >= 99 }
            if let lastFull = fullMarkers.last,
               let prevFull = fullMarkers.dropLast().last {
                let lower = prevFull.timestamp
                let upper = lastFull.timestamp
                let energyDelivered = sessionsAsSource
                    .filter { $0.startedAt <= upper && ($0.endedAt ?? $0.lastObservedAt) >= lower }
                    .reduce(0.0) { $0 + $1.measuredEnergyWh }
                if energyDelivered > 0.1 {
                    apparentCapacity = energyDelivered
                }
            }
        case .percent, .bars:
            if powerbankCheckpoints.count >= 2 {
                let last = powerbankCheckpoints.last!
                if let earlier = powerbankCheckpoints.first(where: {
                    abs(last.batteryPercent - $0.batteryPercent) >= 30
                }) {
                    let lower = min(earlier.timestamp, last.timestamp)
                    let upper = max(earlier.timestamp, last.timestamp)
                    let energyDelivered = sessionsAsSource
                        .filter { $0.startedAt <= upper && ($0.endedAt ?? $0.lastObservedAt) >= lower }
                        .reduce(0.0) { $0 + $1.measuredEnergyWh }
                    if energyDelivered > 0.1 {
                        apparentCapacity = energyDelivered
                    }
                }
            }
        case .none:
            break
        }

        return (voltageMaxCurrents, maxPower, efficiency, apparentCapacity)
    }

    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
}
