<?php

namespace Functional\Streaks\Console\Commands;

use Carbon\Carbon;
use Functional\Streaks\Models\Streak;
use Functional\Streaks\Notifications\StreakAtRiskNotification;
use Illuminate\Console\Command;

/**
 * Rappelle aux utilisateurs de ne pas perdre leur série.
 * Planifiée toutes les heures : pour chaque user dont la série est VIVANTE mais pas entretenue
 * aujourd'hui, on envoie un push le soir (fenêtre 18h-22h locale), 1 fois/jour max.
 */
class RemindStreaksCommand extends Command
{
    protected $signature = 'streaks:remind {--force : ignore la fenêtre horaire (test)}';

    protected $description = 'Envoie un rappel push aux utilisateurs dont la série est en danger.';

    private const WINDOW_START = 18;

    private const WINDOW_END = 22;

    public function handle(): int
    {
        $defaultTz = config('app.timezone', 'UTC');
        $force = (bool) $this->option('force');
        $sent = 0;

        Streak::query()
            ->where('current_count', '>=', 1)
            ->with('user')
            ->chunkById(200, function ($streaks) use ($defaultTz, $force, &$sent) {
                foreach ($streaks as $streak) {
                    $user = $streak->user;
                    if (! $user) {
                        continue;
                    }

                    $tz = $user->timezone ?: $defaultTz;
                    $now = Carbon::now($tz);
                    $today = $now->toDateString();
                    $yesterday = $now->copy()->subDay()->toDateString();
                    $lastActive = $streak->last_active_date?->toDateString();
                    $lastReminded = $streak->last_reminded_on?->toDateString();

                    // Fenêtre horaire du soir (sauf --force).
                    if (! $force && ($now->hour < self::WINDOW_START || $now->hour >= self::WINDOW_END)) {
                        continue;
                    }
                    // Déjà entraîné aujourd'hui → rien à rappeler.
                    if ($lastActive === $today) {
                        continue;
                    }
                    // Série vivante = dernière activité HIER (sinon déjà cassée / gérée par les freezes).
                    if ($lastActive !== $yesterday) {
                        continue;
                    }
                    // Déjà rappelé aujourd'hui.
                    if ($lastReminded === $today) {
                        continue;
                    }
                    // Pas d'abonnement push → inutile.
                    if ($user->pushSubscriptions()->count() === 0) {
                        continue;
                    }

                    $user->notify(new StreakAtRiskNotification((int) $streak->current_count));
                    $streak->forceFill(['last_reminded_on' => $today])->save();
                    $sent++;
                }
            });

        $this->info("Rappels envoyés : {$sent}");

        return self::SUCCESS;
    }
}
