<?php

namespace App\Notifications\Channels;

use App\Services\ApiLogger;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Throwable;

/**
 * Sends push notifications via the OneSignal REST API.
 *
 * Notifications targeting this channel must implement `toOneSignal($notifiable)`
 * returning ['heading' => string, 'message' => string] (or `null` to skip).
 *
 * No-ops when ONESIGNAL_APP_ID/API_KEY are unset, when the notifiable user has
 * no `push_token`, or when toOneSignal() returns null. Each call is logged to
 * api_logs through ApiLogger.
 */
final class OneSignalChannel
{
    public const string NAME = 'onesignal';

    public function __construct(
        private readonly ApiLogger $apiLogger,
    ) {}

    public function send(mixed $notifiable, Notification $notification): void
    {
        $appId = config('services.onesignal.app_id');
        $apiKey = config('services.onesignal.api_key');

        if ($appId === null || $apiKey === null) {
            Log::info('OneSignalChannel: skipped — credentials not configured');

            return;
        }

        $playerId = $notifiable->push_token ?? null;

        if ($playerId === null) {
            return;
        }

        $payload = method_exists($notification, 'toOneSignal')
            ? $notification->toOneSignal($notifiable)
            : null;

        if ($payload === null) {
            return;
        }

        $url = 'https://api.onesignal.com/notifications';

        try {
            $this->apiLogger->send(self::NAME, 'POST', $url, fn () => Http::timeout(10)
                ->withToken($apiKey)
                ->acceptJson()
                ->post($url, [
                    'app_id' => $appId,
                    'include_player_ids' => [$playerId],
                    'headings' => ['en' => $payload['heading'] ?? 'Fuel Alert'],
                    'contents' => ['en' => $payload['message'] ?? ''],
                ]));
        } catch (Throwable $e) {
            Log::error('OneSignalChannel: send failed', ['error' => $e->getMessage()]);
        }
    }
}
