package com.tt.honeyDue.widget

import android.content.Context
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.glance.appwidget.GlanceAppWidgetManager
import androidx.glance.appwidget.state.updateAppWidgetState
import androidx.glance.state.PreferencesGlanceStateDefinition
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

/**
 * Manager for updating all widgets with new data
 */
object WidgetUpdateManager {

    private val json = Json { ignoreUnknownKeys = true }

    /**
     * Update all honeyDue widgets with new data
     */
    fun updateAllWidgets(context: Context) {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                val repository = WidgetDataRepository.getInstance(context)
                val summary = repository.widgetSummary.first()
                val isProUser = repository.isProUser.first()

                updateWidgetsWithData(context, summary, isProUser)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    /**
     * Update widgets with the provided summary data
     */
    suspend fun updateWidgetsWithData(
        context: Context,
        summary: WidgetSummary,
        isProUser: Boolean
    ) {
        val glanceManager = GlanceAppWidgetManager(context)

        // Update small widgets
        val smallWidgetIds = glanceManager.getGlanceIds(HoneyDueSmallWidget::class.java)
        smallWidgetIds.forEach { id ->
            updateAppWidgetState(context, PreferencesGlanceStateDefinition, id) { prefs ->
                prefs.toMutablePreferences().apply {
                    this[intPreferencesKey("overdue_count")] = summary.overdueCount
                    this[intPreferencesKey("due_soon_count")] = summary.dueSoonCount
                    this[intPreferencesKey("in_progress_count")] = summary.inProgressCount
                }
            }
            HoneyDueSmallWidget().update(context, id)
        }

        // Update medium widgets
        val mediumWidgetIds = glanceManager.getGlanceIds(HoneyDueMediumWidget::class.java)
        mediumWidgetIds.forEach { id ->
            updateAppWidgetState(context, PreferencesGlanceStateDefinition, id) { prefs ->
                prefs.toMutablePreferences().apply {
                    this[intPreferencesKey("overdue_count")] = summary.overdueCount
                    this[intPreferencesKey("due_soon_count")] = summary.dueSoonCount
                    this[intPreferencesKey("in_progress_count")] = summary.inProgressCount
                    this[stringPreferencesKey("tasks_json")] = json.encodeToString(summary.tasks)
                }
            }
            HoneyDueMediumWidget().update(context, id)
        }

        // Update large widgets
        val largeWidgetIds = glanceManager.getGlanceIds(HoneyDueLargeWidget::class.java)
        largeWidgetIds.forEach { id ->
            updateAppWidgetState(context, PreferencesGlanceStateDefinition, id) { prefs ->
                prefs.toMutablePreferences().apply {
                    this[intPreferencesKey("overdue_count")] = summary.overdueCount
                    this[intPreferencesKey("due_soon_count")] = summary.dueSoonCount
                    this[intPreferencesKey("in_progress_count")] = summary.inProgressCount
                    this[intPreferencesKey("total_tasks_count")] = summary.totalTasksCount
                    this[stringPreferencesKey("tasks_json")] = json.encodeToString(summary.tasks)
                    this[stringPreferencesKey("is_pro_user")] = if (isProUser) "true" else "false"
                    this[longPreferencesKey("last_updated")] = summary.lastUpdated
                }
            }
            HoneyDueLargeWidget().update(context, id)
        }
    }

    /**
     * Clear all widget data (called on logout)
     */
    fun clearAllWidgets(context: Context) {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                val emptyData = WidgetSummary()
                updateWidgetsWithData(context, emptyData, false)

                // Also clear the repository
                val repository = WidgetDataRepository.getInstance(context)
                repository.clearData()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}
