<?php

namespace App\Services;

use App\Models\DeviceToken;
use App\Models\PushNotificationLog;
use App\Models\User;
use App\Notifications\Push\BasePushNotification;
use Illuminate\Support\Collection;
use Kreait\Firebase\Contract\Messaging;
use Kreait\Firebase\Messaging\AndroidConfig;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Notification;

class PushNotificationService
{
    public function __construct(private Messaging $messaging) {}

    /**
     * Envia uma push notification para todos os tokens ativos de um usuário.
     * Registra o envio no log e desativa tokens inválidos automaticamente.
     */
    public function sendToUser(User $user, BasePushNotification $notification): void
    {
        if (! $user->push_notifications_enabled) {
            return;
        }

        $tokens = DeviceToken::where('user_id', $user->id)
            ->where('app_type', $notification->target()->value)
            ->where('active', true)
            ->pluck('token')
            ->toArray();

        if (empty($tokens)) {
            return;
        }

        $message = CloudMessage::new()
            ->withNotification(
                Notification::create(
                    $notification->title(),
                    $notification->body()
                )
            )
            ->withAndroidConfig(AndroidConfig::fromArray([
                'notification' => ['channel_id' => 'diaria'],
                'priority' => 'high',
            ]));

        $report = $this->messaging->sendMulticast($message, $tokens);

        $this->deactivateInvalidTokens($report->invalidTokens());

        if ($report->successes()->count() > 0) {
            $this->log($user, $notification);
        }
    }

    /**
     * Envia para uma coleção de usuários, respeitando cooldowns.
     * Usuários sem tokens ativos são ignorados silenciosamente.
     */
    public function sendToUsers(Collection $users, BasePushNotification $notification): void
    {
        foreach ($users as $user) {
            $this->sendToUser($user, $notification);
        }
    }

    //

    private function deactivateInvalidTokens(array $tokens): void
    {
        if (empty($tokens)) {
            return;
        }

        DeviceToken::whereIn('token', $tokens)->update(['active' => false]);
    }

    private function log(User $user, BasePushNotification $notification): void
    {
        PushNotificationLog::create([
            'label'    => $notification->label(),
            'user_id'  => $user->id,
            'target'   => $notification->target()->value,
            'category' => $notification->category()->value,
            'sent_at'  => now(),
        ]);
    }
}
