/**
 * NotificationConfigDAO.swift
 * 
 * Data Access Object (DAO) for NotificationConfig Core Data entity
 * Provides CRUD operations and query helpers for notification configuration
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 * @created 2025-12-08
 */

import Foundation
import CoreData

/**
 * Extension providing DAO methods for NotificationConfig entity
 * 
 * This extension adds CRUD operations and query helpers to the
 * auto-generated NotificationConfig Core Data class.
 */
extension NotificationConfig {
    
    // MARK: - Constants
    
    private static let TAG = "DNP-NOTIFICATION-CONFIG-DAO"
    
    // MARK: - Create/Insert Methods
    
    /**
     * Create a new NotificationConfig entity in the given context
     * 
     * @param context Core Data managed object context
     * @param id Unique configuration identifier
     * @param timesafariDid TimeSafari device ID
     * @param configType Type of configuration
     * @param configKey Configuration key
     * @param configValue Configuration value (string representation)
     * @param configDataType Data type of value (e.g., "string", "int", "bool", "json")
     * @param isEncrypted Whether value is encrypted
     * @param encryptionKeyId Encryption key identifier
     * @param ttlSeconds Time-to-live in seconds
     * @param isActive Whether configuration is active
     * @param metadata Additional metadata (JSON string)
     * @return Created NotificationConfig entity
     */
    static func create(
        in context: NSManagedObjectContext,
        id: String,
        timesafariDid: String? = nil,
        configType: String? = nil,
        configKey: String? = nil,
        configValue: String? = nil,
        configDataType: String? = nil,
        isEncrypted: Bool = false,
        encryptionKeyId: String? = nil,
        ttlSeconds: Int64 = 604800, // 7 days default
        isActive: Bool = true,
        metadata: String? = nil
    ) -> NotificationConfig {
        let entity = NotificationConfig(context: context)
        let now = Date()
        
        entity.id = id
        entity.timesafariDid = timesafariDid
        entity.configType = configType
        entity.configKey = configKey
        entity.configValue = configValue
        entity.configDataType = configDataType
        entity.isEncrypted = isEncrypted
        entity.encryptionKeyId = encryptionKeyId
        entity.createdAt = now
        entity.updatedAt = now
        entity.ttlSeconds = ttlSeconds
        entity.isActive = isActive
        entity.metadata = metadata
        
        print("\(Self.TAG): Created NotificationConfig with id: \(id)")
        return entity
    }
    
    /**
     * Create from dictionary representation
     * 
     * @param context Core Data managed object context
     * @param dict Dictionary with configuration data
     * @return Created NotificationConfig entity or nil
     */
    static func create(
        in context: NSManagedObjectContext,
        from dict: [String: Any]
    ) -> NotificationConfig? {
        guard let id = dict["id"] as? String else {
            print("\(Self.TAG): Missing required 'id' field")
            return nil
        }
        
        // Convert createdAt/updatedAt if present
        let createdAt: Date
        if let createdMillis = dict["createdAt"] as? Int64 {
            createdAt = DailyNotificationDataConversions.dateFromEpochMillis(createdMillis)
        } else if let createdDate = dict["createdAt"] as? Date {
            createdAt = createdDate
        } else {
            createdAt = Date()
        }
        
        let updatedAt: Date
        if let updatedMillis = dict["updatedAt"] as? Int64 {
            updatedAt = DailyNotificationDataConversions.dateFromEpochMillis(updatedMillis)
        } else if let updatedDate = dict["updatedAt"] as? Date {
            updatedAt = updatedDate
        } else {
            updatedAt = Date()
        }
        
        let entity = NotificationConfig(context: context)
        entity.id = id
        entity.timesafariDid = dict["timesafariDid"] as? String
        entity.configType = dict["configType"] as? String
        entity.configKey = dict["configKey"] as? String
        entity.configValue = dict["configValue"] as? String
        entity.configDataType = dict["configDataType"] as? String
        entity.isEncrypted = dict["isEncrypted"] as? Bool ?? false
        entity.encryptionKeyId = dict["encryptionKeyId"] as? String
        entity.createdAt = createdAt
        entity.updatedAt = updatedAt
        entity.ttlSeconds = dict["ttlSeconds"] as? Int64 ?? 604800
        entity.isActive = dict["isActive"] as? Bool ?? true
        entity.metadata = dict["metadata"] as? String
        
        return entity
    }
    
    // MARK: - Read/Query Methods
    
    /**
     * Fetch NotificationConfig by ID
     * 
     * @param context Core Data managed object context
     * @param id Configuration ID
     * @return NotificationConfig entity or nil
     */
    static func fetch(
        by id: String,
        in context: NSManagedObjectContext
    ) -> NotificationConfig? {
        let request: NSFetchRequest<NotificationConfig> = NotificationConfig.fetchRequest()
        request.predicate = NSPredicate(format: "id == %@", id)
        request.fetchLimit = 1
        
        do {
            let results = try context.fetch(request)
            return results.first
        } catch {
            print("\(Self.TAG): Error fetching by id: \(error.localizedDescription)")
            return nil
        }
    }
    
    /**
     * Fetch NotificationConfig by key (configKey)
     * 
     * @param context Core Data managed object context
     * @param configKey Configuration key
     * @return NotificationConfig entity or nil
     */
    static func fetchByConfigKey(
        _ configKey: String,
        in context: NSManagedObjectContext
    ) -> NotificationConfig? {
        let request: NSFetchRequest<NotificationConfig> = NotificationConfig.fetchRequest()
        request.predicate = NSPredicate(format: "configKey == %@", configKey)
        request.fetchLimit = 1
        
        do {
            let results = try context.fetch(request)
            return results.first
        } catch {
            print("\(Self.TAG): Error fetching by configKey: \(error.localizedDescription)")
            return nil
        }
    }
    
    /**
     * Fetch all NotificationConfig entities
     * 
     * @param context Core Data managed object context
     * @return Array of NotificationConfig entities
     */
    static func fetchAll(
        in context: NSManagedObjectContext
    ) -> [NotificationConfig] {
        let request: NSFetchRequest<NotificationConfig> = NotificationConfig.fetchRequest()
        
        do {
            return try context.fetch(request)
        } catch {
            print("\(Self.TAG): Error fetching all: \(error.localizedDescription)")
            return []
        }
    }
    
    /**
     * Query by timesafariDid
     * 
     * @param context Core Data managed object context
     * @param timesafariDid TimeSafari device ID
     * @return Array of NotificationConfig entities
     */
    static func queryByTimesafariDid(
        _ timesafariDid: String,
        in context: NSManagedObjectContext
    ) -> [NotificationConfig] {
        let request: NSFetchRequest<NotificationConfig> = NotificationConfig.fetchRequest()
        request.predicate = NSPredicate(format: "timesafariDid == %@", timesafariDid)
        request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
        
        do {
            return try context.fetch(request)
        } catch {
            print("\(Self.TAG): Error querying by timesafariDid: \(error.localizedDescription)")
            return []
        }
    }
    
    /**
     * Query by configType
     * 
     * @param context Core Data managed object context
     * @param configType Configuration type
     * @return Array of NotificationConfig entities
     */
    static func queryByConfigType(
        _ configType: String,
        in context: NSManagedObjectContext
    ) -> [NotificationConfig] {
        let request: NSFetchRequest<NotificationConfig> = NotificationConfig.fetchRequest()
        request.predicate = NSPredicate(format: "configType == %@", configType)
        request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
        
        do {
            return try context.fetch(request)
        } catch {
            print("\(Self.TAG): Error querying by configType: \(error.localizedDescription)")
            return []
        }
    }
    
    /**
     * Query active configurations only
     * 
     * @param context Core Data managed object context
     * @return Array of active NotificationConfig entities
     */
    static func queryActive(
        in context: NSManagedObjectContext
    ) -> [NotificationConfig] {
        let request: NSFetchRequest<NotificationConfig> = NotificationConfig.fetchRequest()
        request.predicate = NSPredicate(format: "isActive == YES")
        request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
        
        do {
            return try context.fetch(request)
        } catch {
            print("\(Self.TAG): Error querying active: \(error.localizedDescription)")
            return []
        }
    }
    
    /**
     * Query by configType and isActive
     * 
     * @param context Core Data managed object context
     * @param configType Configuration type
     * @param isActive Whether configuration is active
     * @return Array of NotificationConfig entities
     */
    static func query(
        by configType: String,
        isActive: Bool,
        in context: NSManagedObjectContext
    ) -> [NotificationConfig] {
        let request: NSFetchRequest<NotificationConfig> = NotificationConfig.fetchRequest()
        request.predicate = NSPredicate(
            format: "configType == %@ AND isActive == %@",
            configType,
            NSNumber(value: isActive)
        )
        request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
        
        do {
            return try context.fetch(request)
        } catch {
            print("\(Self.TAG): Error querying by configType and isActive: \(error.localizedDescription)")
            return []
        }
    }
    
    // MARK: - Update Methods
    
    /**
     * Update configuration value
     * 
     * @param value New configuration value
     */
    func updateValue(_ value: String?) {
        self.configValue = value
        self.updatedAt = Date()
    }
    
    /**
     * Activate or deactivate configuration
     * 
     * @param active Whether configuration should be active
     */
    func setActive(_ active: Bool) {
        self.isActive = active
        self.updatedAt = Date()
    }
    
    /**
     * Update this entity's updatedAt timestamp
     */
    func touch() {
        self.updatedAt = Date()
    }
    
    // MARK: - Delete Methods
    
    /**
     * Delete NotificationConfig by ID
     * 
     * @param context Core Data managed object context
     * @param id Configuration ID
     * @return true if deleted, false otherwise
     */
    static func delete(
        by id: String,
        in context: NSManagedObjectContext
    ) -> Bool {
        guard let entity = fetch(by: id, in: context) else {
            return false
        }
        
        context.delete(entity)
        
        do {
            try context.save()
            print("\(Self.TAG): Deleted NotificationConfig with id: \(id)")
            return true
        } catch {
            print("\(Self.TAG): Error deleting: \(error.localizedDescription)")
            context.rollback()
            return false
        }
    }
    
    /**
     * Delete NotificationConfig by configKey
     * 
     * @param context Core Data managed object context
     * @param configKey Configuration key
     * @return true if deleted, false otherwise
     */
    static func deleteByConfigKey(
        _ configKey: String,
        in context: NSManagedObjectContext
    ) -> Bool {
        guard let entity = fetchByConfigKey(configKey, in: context) else {
            return false
        }
        
        context.delete(entity)
        
        do {
            try context.save()
            print("\(Self.TAG): Deleted NotificationConfig with configKey: \(configKey)")
            return true
        } catch {
            print("\(Self.TAG): Error deleting: \(error.localizedDescription)")
            context.rollback()
            return false
        }
    }
    
    /**
     * Delete all NotificationConfig entities
     * 
     * @param context Core Data managed object context
     * @return Number of entities deleted
     */
    static func deleteAll(
        in context: NSManagedObjectContext
    ) -> Int {
        let request: NSFetchRequest<NSFetchRequestResult> = NotificationConfig.fetchRequest()
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: request)
        
        do {
            let result = try context.execute(deleteRequest) as? NSBatchDeleteResult
            try context.save()
            let count = result?.result as? Int ?? 0
            print("\(Self.TAG): Deleted \(count) NotificationConfig entities")
            return count
        } catch {
            print("\(Self.TAG): Error deleting all: \(error.localizedDescription)")
            context.rollback()
            return 0
        }
    }
}

