package org.timesafari.dailynotification

import android.content.Context
import android.util.Log
import org.json.JSONObject

/**
 * Re-enqueues dual (New Activity) prefetch from persisted SharedPreferences config
 * (boot recovery, after a successful dual fetch rollover).
 */
object DualScheduleFetchRecovery {
    private const val TAG = "DNP-DUAL-RECOVER"

    /**
     * Parses [DailyNotificationConstants.DUAL_SCHEDULE_CONFIG_KEY] and enqueues the next delayed dual fetch.
     * @return true if a job was scheduled
     */
    @JvmStatic
    fun enqueueFromPersistedConfig(context: Context): Boolean {
        return try {
            val prefs = context.getSharedPreferences(
                DailyNotificationConstants.DUAL_SCHEDULE_PREFS,
                Context.MODE_PRIVATE
            )
            val jsonStr = prefs.getString(DailyNotificationConstants.DUAL_SCHEDULE_CONFIG_KEY, null)
                ?: return false
            val root = JSONObject(jsonStr)
            val contentFetchObj = root.optJSONObject("contentFetch") ?: return false
            val userNotificationObj = root.optJSONObject("userNotification") ?: return false
            val contentFetchConfig = parseContentFetchConfigJson(contentFetchObj)
            val userNotificationConfig = parseUserNotificationConfigJson(userNotificationObj)
            if (!contentFetchConfig.enabled) {
                Log.d(TAG, "contentFetch disabled, skip dual fetch recovery")
                return false
            }
            val nextFetchAt = ScheduleCronUtils.calculateNextRunTimeMillis(contentFetchConfig.schedule)
            val nextNotifyAt = ScheduleCronUtils.calculateNextRunTimeMillis(userNotificationConfig.schedule)
            FetchWorker.enqueueDualFetch(
                context,
                contentFetchConfig,
                nextFetchAt,
                nextNotifyAt
            )
            true
        } catch (e: Exception) {
            Log.w(TAG, "enqueueFromPersistedConfig failed", e)
            false
        }
    }

    private fun parseContentFetchConfigJson(configJson: JSONObject): ContentFetchConfig {
        val callbacksObj = configJson.optJSONObject("callbacks")
        return ContentFetchConfig(
            enabled = configJson.optBoolean("enabled", true),
            schedule = configJson.optString("schedule", "0 9 * * *"),
            url = configJson.optString("url").takeIf { it.isNotEmpty() },
            timeout = configJson.takeUnless { !it.has("timeout") || JSONObject.NULL == it.get("timeout") }
                ?.optInt("timeout"),
            retryAttempts = configJson.takeUnless { !it.has("retryAttempts") || JSONObject.NULL == it.get("retryAttempts") }
                ?.optInt("retryAttempts"),
            retryDelay = configJson.takeUnless { !it.has("retryDelay") || JSONObject.NULL == it.get("retryDelay") }
                ?.optInt("retryDelay"),
            callbacks = CallbackConfig(
                apiService = callbacksObj?.optString("apiService")?.takeIf { it.isNotEmpty() },
                database = callbacksObj?.optString("database")?.takeIf { it.isNotEmpty() },
                reporting = callbacksObj?.optString("reporting")?.takeIf { it.isNotEmpty() }
            )
        )
    }

    private fun parseUserNotificationConfigJson(configJson: JSONObject): UserNotificationConfig {
        return UserNotificationConfig(
            enabled = configJson.optBoolean("enabled", true),
            schedule = configJson.optString("schedule", "0 9 * * *"),
            title = configJson.optString("title").takeIf { it.isNotEmpty() },
            body = configJson.optString("body").takeIf { it.isNotEmpty() },
            sound = if (configJson.has("sound") && JSONObject.NULL != configJson.get("sound")) configJson.optBoolean("sound") else null,
            vibration = if (configJson.has("vibration") && JSONObject.NULL != configJson.get("vibration")) configJson.optBoolean("vibration") else null,
            priority = configJson.optString("priority").takeIf { it.isNotEmpty() }
        )
    }
}
