package legion.muyue.best2048;

import android.content.Context;
import android.content.SharedPreferences;

import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

import java.util.concurrent.TimeUnit;

/**
 * Un {@link Worker} Android conçu pour s'exécuter périodiquement en arrière-plan
 * via {@link androidx.work.WorkManager}.
 * Sa tâche est de vérifier si certaines conditions sont remplies pour envoyer
 * des notifications à l'utilisateur, telles qu'un rappel de son meilleur score
 * ou une notification d'inactivité pour l'encourager à rejouer.
 * Les conditions, seuils et états (comme la dernière fois jouée ou notifiée)
 * sont gérés via {@link SharedPreferences}.
 */
public class NotificationWorker extends Worker {

    // --- Constantes ---

    /** Identifiant unique pour la notification de rappel du meilleur score. */
    private static final int NOTIFICATION_ID_HIGHSCORE = 2;
    /** Identifiant unique pour la notification d'inactivité. */
    private static final int NOTIFICATION_ID_INACTIVITY = 3;

    /** Intervalle minimum (en millisecondes) entre deux notifications de rappel du meilleur score. (1 jour) */
    private static final long HIGHSCORE_INTERVAL_MS = TimeUnit.DAYS.toMillis(1);
    /** Seuil d'inactivité (en millisecondes) : durée depuis la dernière partie jouée au-delà de laquelle une notification peut être envoyée. (3 jours) */
    private static final long INACTIVITY_THRESHOLD_MS = TimeUnit.DAYS.toMillis(3);
    /** Temps de recharge minimum (en millisecondes) entre deux notifications d'inactivité. (1 jour) */
    private static final long INACTIVITY_NOTIFICATION_COOLDOWN_MS = TimeUnit.DAYS.toMillis(1);

    /** Nom du fichier SharedPreferences utilisé par cette classe et potentiellement d'autres (ex: GameStats). */
    private static final String PREFS_NAME = "Best2048_Prefs";
    /** Clé SharedPreferences pour le meilleur score (utilisé aussi par GameStats). */
    private static final String HIGH_SCORE_KEY = "high_score";
    /** Clé SharedPreferences pour stocker le timestamp de la dernière fois où l'utilisateur a joué. */
    private static final String LAST_PLAYED_TIME_KEY = "last_played_time";
    /** Clé SharedPreferences pour l'activation globale des notifications par l'utilisateur. */
    private static final String NOTIFICATIONS_ENABLED_KEY = "notifications_enabled";
    /** Clé SharedPreferences pour stocker le timestamp de la dernière notification de meilleur score envoyée. */
    private static final String LAST_HS_NOTIFICATION_TIME = "lastHsNotificationTime";
    /** Clé SharedPreferences pour stocker le timestamp de la dernière notification d'inactivité envoyée. */
    private static final String LAST_INACTIVITY_NOTIFICATION_TIME = "lastInactivityNotificationTime";

    /**
     * Constructeur standard pour un {@link Worker}.
     *
     * @param context      Le contexte de l'application.
     * @param workerParams Paramètres pour le Worker, fournis par WorkManager.
     */
    public NotificationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    /**
     * Exécute la tâche principale du Worker en arrière-plan.
     * Vérifie si les notifications sont activées, puis évalue les conditions pour
     * envoyer une notification de meilleur score ou une notification d'inactivité.
     * Met à jour les timestamps des dernières notifications envoyées si nécessaire.
     * Cette méthode est appelée par WorkManager sur un thread d'arrière-plan.
     *
     * @return {@link Result#success()} si le travail s'est terminé (qu'une notification ait été envoyée ou non).
     * Retourne {@link Result#failure()} ou {@link Result#retry()} en cas d'erreur non récupérable ou si le travail doit être retenté.
     * Ici, on retourne toujours success() même en cas d'exception interne pour ne pas bloquer les exécutions futures,
     * mais un logging serait approprié.
     */
    @NonNull
    @Override
    public Result doWork() {
        Context context = getApplicationContext();
        SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);

        // 1. Vérifier si les notifications sont activées globalement
        boolean notificationsEnabled = prefs.getBoolean(NOTIFICATIONS_ENABLED_KEY, false);
        if (!notificationsEnabled) {
            return Result.success(); // Travail terminé avec succès (rien à faire)
        }

        long currentTime = System.currentTimeMillis();

        // 2. Vérification pour la notification du meilleur score
        try {
            long lastHsNotificationTime = prefs.getLong(LAST_HS_NOTIFICATION_TIME, 0);
            // Vérifier si l'intervalle depuis la dernière notification de high score est dépassé
            if (currentTime - lastHsNotificationTime > HIGHSCORE_INTERVAL_MS) {
                int highScore = prefs.getInt(HIGH_SCORE_KEY, 0);
                // Vérifier s'il y a un high score à afficher (> 0)
                if (highScore > 0) {
                    showHighScoreNotificationNow(context, highScore);
                    // Mettre à jour le timestamp de la dernière notification de high score
                    prefs.edit().putLong(LAST_HS_NOTIFICATION_TIME, currentTime).apply();
                }
            }
        } catch (Exception e) {
        }

        // 3. Vérification pour la notification d'inactivité
        try {
            long lastPlayedTime = prefs.getLong(LAST_PLAYED_TIME_KEY, 0);
            long lastInactivityNotificationTime = prefs.getLong(LAST_INACTIVITY_NOTIFICATION_TIME, 0);

            // Condition 1: L'utilisateur n'a pas joué depuis un certain temps (INACTIVITY_THRESHOLD_MS)
            boolean isInactivityThresholdMet = (lastPlayedTime > 0 && currentTime - lastPlayedTime > INACTIVITY_THRESHOLD_MS);
            // Condition 2: Assez de temps s'est écoulé depuis la dernière notification d'inactivité (cooldown)
            boolean isCooldownMet = (currentTime - lastInactivityNotificationTime > INACTIVITY_NOTIFICATION_COOLDOWN_MS);

            if (isInactivityThresholdMet && isCooldownMet) {
                showInactivityNotificationNow(context);
                // Mettre à jour le timestamp de la dernière notification d'inactivité
                prefs.edit().putLong(LAST_INACTIVITY_NOTIFICATION_TIME, currentTime).apply();
            }
        } catch (Exception e) {
        }
        return Result.success();
    }

    /**
     * Construit et affiche immédiatement la notification de rappel du meilleur score.
     * Utilise une classe helper {@code NotificationHelper} (non fournie ici) pour la logique d'affichage réelle.
     * Récupère les textes depuis les ressources de chaînes Android (R.string).
     *
     * @param context   Le contexte applicatif.
     * @param highScore Le meilleur score actuel de l'utilisateur à afficher.
     */
    private void showHighScoreNotificationNow(Context context, int highScore) {
        String title = context.getString(R.string.notification_title_highscore);
        String message = context.getString(R.string.notification_text_highscore, highScore);
        NotificationHelper.showNotification(context, title, message, NOTIFICATION_ID_HIGHSCORE);
    }

    /**
     * Construit et affiche immédiatement la notification d'inactivité.
     * Utilise une classe helper {@code NotificationHelper} (non fournie ici) pour la logique d'affichage réelle.
     * Récupère les textes depuis les ressources de chaînes Android (R.string).
     *
     * @param context Le contexte applicatif.
     */
    private void showInactivityNotificationNow(Context context) {
        String title = context.getString(R.string.notification_title_inactivity);
        String message = context.getString(R.string.notification_text_inactivity);
        NotificationHelper.showNotification(context, title, message, NOTIFICATION_ID_INACTIVITY);
    }
}