package app.closer.data.local

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import app.closer.core.notifications.QuietHours
import app.closer.domain.repository.AppSettings
import app.closer.domain.repository.SettingsRepository
import app.closer.domain.repository.ThemeMode
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class SettingsDataStore @Inject constructor(
    private val dataStore: DataStore<Preferences>
) : SettingsRepository {

    private val DAILY_REMINDER = booleanPreferencesKey("daily_reminder")
    private val PARTNER_ANSWERED = booleanPreferencesKey("partner_answered")
    private val CHAT_MESSAGE = booleanPreferencesKey("chat_message")
    private val STREAK_REMINDER = booleanPreferencesKey("streak_reminder")
    private val QUIET_HOURS = booleanPreferencesKey("quiet_hours")
    private val QUIET_HOURS_START_HOUR = intPreferencesKey("quiet_hours_start_hour")
    private val QUIET_HOURS_START_MINUTE = intPreferencesKey("quiet_hours_start_minute")
    private val QUIET_HOURS_END_HOUR = intPreferencesKey("quiet_hours_end_hour")
    private val QUIET_HOURS_END_MINUTE = intPreferencesKey("quiet_hours_end_minute")
    private val ONBOARDING_COMPLETE = booleanPreferencesKey("onboarding_complete")
    private val THEME_MODE = stringPreferencesKey("theme_mode")

    private val OUTCOME_REMINDER_ENABLED = booleanPreferencesKey("outcome_reminder_enabled")
    private val OUTCOME_BASELINE_SHOWN_AT = longPreferencesKey("outcome_baseline_shown_at")
    private val OUTCOME_LAST_PROMPTED_DAY = stringPreferencesKey("outcome_last_prompted_day")
    private val BIOMETRIC_LOGIN = booleanPreferencesKey("biometric_login")
    private val LAST_CELEBRATED_STREAK = intPreferencesKey("last_celebrated_streak_milestone")

    override val settings: Flow<AppSettings> = dataStore.data.map { prefs ->
        AppSettings(
            dailyReminderEnabled = prefs[DAILY_REMINDER] ?: true,
            partnerAnsweredEnabled = prefs[PARTNER_ANSWERED] ?: true,
            chatMessageEnabled = prefs[CHAT_MESSAGE] ?: true,
            streakReminderEnabled = prefs[STREAK_REMINDER] ?: false,
            quietHoursEnabled = prefs[QUIET_HOURS] ?: false,
            quietHours = QuietHours(
                enabled = prefs[QUIET_HOURS] ?: false,
                startHour = prefs[QUIET_HOURS_START_HOUR] ?: 22,
                startMinute = prefs[QUIET_HOURS_START_MINUTE] ?: 0,
                endHour = prefs[QUIET_HOURS_END_HOUR] ?: 8,
                endMinute = prefs[QUIET_HOURS_END_MINUTE] ?: 0
            ),
            onboardingComplete = prefs[ONBOARDING_COMPLETE] ?: false,
            themeMode = ThemeMode.fromStorageValue(prefs[THEME_MODE]),
            outcomeReminderEnabled = prefs[OUTCOME_REMINDER_ENABLED] ?: true,
            outcomeBaselineShownAt = prefs[OUTCOME_BASELINE_SHOWN_AT] ?: 0L,
            outcomeLastPromptedDay = prefs[OUTCOME_LAST_PROMPTED_DAY] ?: "",
            biometricLoginEnabled = prefs[BIOMETRIC_LOGIN] ?: false,
            lastCelebratedStreakMilestone = prefs[LAST_CELEBRATED_STREAK] ?: 0
        )
    }

    override suspend fun setLastCelebratedStreakMilestone(milestone: Int) =
        dataStore.edit { it[LAST_CELEBRATED_STREAK] = milestone }.let {}

    override suspend fun setOutcomeReminderEnabled(enabled: Boolean) =
        dataStore.edit { it[OUTCOME_REMINDER_ENABLED] = enabled }.let {}

    override suspend fun markOutcomeBaselineShown() =
        dataStore.edit { it[OUTCOME_BASELINE_SHOWN_AT] = System.currentTimeMillis() }.let {}

    override suspend fun setOutcomeLastPromptedDay(dayKey: String) =
        dataStore.edit { it[OUTCOME_LAST_PROMPTED_DAY] = dayKey }.let {}

    override suspend fun setDailyReminder(enabled: Boolean) =
        dataStore.edit { it[DAILY_REMINDER] = enabled }.let {}

    override suspend fun setPartnerAnswered(enabled: Boolean) =
        dataStore.edit { it[PARTNER_ANSWERED] = enabled }.let {}

    override suspend fun setChatMessage(enabled: Boolean) =
        dataStore.edit { it[CHAT_MESSAGE] = enabled }.let {}

    override suspend fun setStreakReminder(enabled: Boolean) =
        dataStore.edit { it[STREAK_REMINDER] = enabled }.let {}

    override suspend fun setQuietHours(enabled: Boolean) =
        dataStore.edit { it[QUIET_HOURS] = enabled }.let {}

    override suspend fun setQuietHours(quietHours: QuietHours) =
        dataStore.edit {
            it[QUIET_HOURS] = quietHours.enabled
            it[QUIET_HOURS_START_HOUR] = quietHours.startHour
            it[QUIET_HOURS_START_MINUTE] = quietHours.startMinute
            it[QUIET_HOURS_END_HOUR] = quietHours.endHour
            it[QUIET_HOURS_END_MINUTE] = quietHours.endMinute
        }.let {}

    override suspend fun setOnboardingComplete(complete: Boolean) =
        dataStore.edit { it[ONBOARDING_COMPLETE] = complete }.let {}

    override suspend fun setThemeMode(mode: ThemeMode) =
        // Persist every explicit choice, including DEVICE/System. The system theme is the
        // default only on first load (when no key is stored yet → fromStorageValue → DEVICE);
        // once the user picks anything we save it rather than dropping back to "no preference".
        dataStore.edit { it[THEME_MODE] = mode.name }.let {}

    override suspend fun setBiometricLogin(enabled: Boolean) =
        dataStore.edit { it[BIOMETRIC_LOGIN] = enabled }.let {}
}
