/**
 * DailyNotificationDataConversions.swift
 * 
 * Data type conversion helpers for Core Data operations
 * Handles conversions between Swift types and Core Data types,
 * especially for time (Date ↔ Long/Int64) and numeric types.
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 * @created 2025-12-08
 */

import Foundation
import CoreData

/**
 * Data conversion utilities for Core Data operations
 * 
 * This module provides helper functions for converting between:
 * - Date ↔ Int64 (epoch milliseconds)
 * - Int ↔ Int32
 * - Long ↔ Int64
 * - Optional string handling
 */
class DailyNotificationDataConversions {
    
    // MARK: - Constants
    
    private static let TAG = "DNP-DATA-CONVERSIONS"
    
    // MARK: - Time Conversions (Section 6.1)
    
    /**
     * Convert epoch milliseconds (Int64) to Date
     * 
     * @param epochMillis Milliseconds since epoch (1970-01-01 00:00:00 UTC)
     * @return Date object
     */
    static func dateFromEpochMillis(_ epochMillis: Int64) -> Date {
        return Date(timeIntervalSince1970: Double(epochMillis) / 1000.0)
    }
    
    /**
     * Convert Date to epoch milliseconds (Int64)
     * 
     * @param date Date object
     * @return Milliseconds since epoch (1970-01-01 00:00:00 UTC)
     */
    static func epochMillisFromDate(_ date: Date) -> Int64 {
        return Int64(date.timeIntervalSince1970 * 1000.0)
    }
    
    /**
     * Convert optional epoch milliseconds to optional Date
     * 
     * @param epochMillis Optional milliseconds since epoch
     * @return Optional Date object
     */
    static func dateFromEpochMillis(_ epochMillis: Int64?) -> Date? {
        guard let millis = epochMillis else { return nil }
        return dateFromEpochMillis(millis)
    }
    
    /**
     * Convert optional Date to optional epoch milliseconds
     * 
     * @param date Optional Date object
     * @return Optional milliseconds since epoch
     */
    static func epochMillisFromDate(_ date: Date?) -> Int64? {
        guard let dateValue = date else { return nil }
        return epochMillisFromDate(dateValue)
    }
    
    // MARK: - Numeric Conversions (Section 6.2)
    
    /**
     * Convert Int to Int32 (for Core Data Integer 32)
     * 
     * @param value Int value
     * @return Int32 value
     */
    static func int32FromInt(_ value: Int) -> Int32 {
        return Int32(value)
    }
    
    /**
     * Convert Int32 to Int
     * 
     * @param value Int32 value
     * @return Int value
     */
    static func intFromInt32(_ value: Int32) -> Int {
        return Int(value)
    }
    
    /**
     * Convert Int64 to Int32 (with clamping if needed)
     * 
     * @param value Int64 value
     * @return Int32 value (clamped if out of range)
     */
    static func int32FromInt64(_ value: Int64) -> Int32 {
        if value > Int64(Int32.max) {
            return Int32.max
        } else if value < Int64(Int32.min) {
            return Int32.min
        }
        return Int32(value)
    }
    
    /**
     * Convert Int32 to Int64
     * 
     * @param value Int32 value
     * @return Int64 value
     */
    static func int64FromInt32(_ value: Int32) -> Int64 {
        return Int64(value)
    }
    
    /**
     * Convert Long (Int64) to Int64 (no-op, but explicit)
     * 
     * @param value Int64 value
     * @return Int64 value
     */
    static func int64FromLong(_ value: Int64) -> Int64 {
        return value
    }
    
    /**
     * Convert Boolean to Bool (direct, but explicit)
     * 
     * @param value Boolean value
     * @return Bool value
     */
    static func boolFromBoolean(_ value: Bool) -> Bool {
        return value
    }
    
    // MARK: - String Conversions (Section 6.3)
    
    /**
     * Safely convert optional String to String
     * 
     * @param value Optional String
     * @return String (empty string if nil)
     */
    static func stringFromOptional(_ value: String?) -> String {
        return value ?? ""
    }
    
    /**
     * Safely convert String to optional String
     * 
     * @param value String value
     * @return Optional String (nil if empty)
     */
    static func optionalStringFromString(_ value: String) -> String? {
        return value.isEmpty ? nil : value
    }
    
    /**
     * Convert JSON dictionary to JSON string
     * 
     * @param dict Dictionary to encode
     * @return JSON string or nil if encoding fails
     */
    static func jsonStringFromDictionary(_ dict: [String: Any]?) -> String? {
        guard let dict = dict else { return nil }
        guard let data = try? JSONSerialization.data(withJSONObject: dict),
              let jsonString = String(data: data, encoding: .utf8) else {
            return nil
        }
        return jsonString
    }
    
    /**
     * Convert JSON string to dictionary
     * 
     * @param jsonString JSON string to decode
     * @return Dictionary or nil if decoding fails
     */
    static func dictionaryFromJsonString(_ jsonString: String?) -> [String: Any]? {
        guard let jsonString = jsonString,
              let data = jsonString.data(using: .utf8),
              let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
            return nil
        }
        return dict
    }
}

