import Foundation
import CoreData

/// Per-category allocation target (percentage).
///
/// Backed by the `Category.allocationTarget` Core Data attribute so targets sync across
/// devices via iCloud/CloudKit. Previously stored in `UserDefaults`, which is device-local
/// and did NOT sync — `migrateIfNeeded(context:)` moves any legacy values over.
enum AllocationTargetStore {
    /// Legacy UserDefaults key (pre-iCloud). Only read once during migration.
    private static let legacyKey = "allocationTargets"

    private static var viewContext: NSManagedObjectContext { CoreDataStack.shared.viewContext }

    static func target(for categoryId: UUID) -> Double? {
        guard let category = fetchCategory(categoryId),
              let target = category.allocationTarget?.doubleValue,
              target > 0 else { return nil }
        return target
    }

    static func setTarget(_ value: Double?, for categoryId: UUID) {
        guard let category = fetchCategory(categoryId) else { return }
        if let value, value > 0 {
            category.allocationTarget = NSNumber(value: value)
        } else {
            category.allocationTarget = nil
        }
        try? viewContext.save()
    }

    static func totalTargetPercentage(for categoryIds: [UUID]) -> Double {
        categoryIds.reduce(0) { total, id in
            total + (target(for: id) ?? 0)
        }
    }

    private static func fetchCategory(_ id: UUID) -> Category? {
        let request = Category.fetchRequest()
        request.predicate = NSPredicate(format: "id == %@", id as CVarArg)
        request.fetchLimit = 1
        return try? viewContext.fetch(request).first
    }

    // MARK: - Migration

    /// One-time migration of legacy UserDefaults targets into Core Data so they sync via
    /// iCloud. Runs on every launch but is a no-op once the legacy key is cleared.
    static func migrateIfNeeded(context: NSManagedObjectContext) {
        guard let data = UserDefaults.standard.data(forKey: legacyKey),
              let dict = try? JSONDecoder().decode([String: Double].self, from: data),
              !dict.isEmpty else { return }

        let categories = (try? context.fetch(Category.fetchRequest())) ?? []
        var changed = false
        for category in categories where category.allocationTarget == nil {
            if let value = dict[category.id.uuidString], value > 0 {
                category.allocationTarget = NSNumber(value: value)
                changed = true
            }
        }
        if changed { try? context.save() }
        UserDefaults.standard.removeObject(forKey: legacyKey)
    }
}
