<?php

namespace App\Services;

use App\Models\DeviceToken;
use App\Services\MobileConfig\MobileConfigService;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class FcmService
{
    private string $serverKey;

    private string $endpoint = 'https://fcm.googleapis.com/fcm/send';

    protected $mobileConfig;

    public function __construct(MobileConfigService $mobileConfig)
    {
        $this->serverKey = config('services.fcm.server_key', '');
        $this->mobileConfig = $mobileConfig;
    }

    /**
     * Check if notifications are enabled globally in settings.
     */
    private function isEnabled(): bool
    {
        $config = $this->mobileConfig->all();

        return filter_var($config['notifications']['enable_push_notifications'] ?? true, FILTER_VALIDATE_BOOLEAN);
    }

    /**
     * Send push notification to a single user (all their devices).
     */
    public function sendToUser(int $userId, string $title, string $body, array $data = []): void
    {
        if (! $this->isEnabled()) {
            return;
        }

        $tokens = DeviceToken::where('user_id', $userId)->pluck('token')->toArray();

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

        $this->sendToTokens($tokens, $title, $body, $data);
    }

    /**
     * Send to a list of device tokens.
     */
    public function sendToTokens(array $tokens, string $title, string $body, array $data = []): void
    {
        if (! $this->isEnabled()) {
            return;
        }

        if (empty($this->serverKey)) {
            Log::warning('FCM server key not configured — push notification skipped');

            return;
        }

        // FCM supports max 1000 tokens per request
        foreach (array_chunk($tokens, 1000) as $chunk) {
            $this->dispatch($chunk, $title, $body, $data);
        }
    }

    private function dispatch(array $tokens, string $title, string $body, array $data): void
    {
        $payload = [
            'registration_ids' => $tokens,
            'notification' => ['title' => $title, 'body' => $body],
            'data' => $data,
            'priority' => 'high',
        ];

        try {
            $response = Http::withHeaders([
                'Authorization' => 'key='.$this->serverKey,
                'Content-Type' => 'application/json',
            ])->post($this->endpoint, $payload);

            if (! $response->successful()) {
                Log::error('FCM dispatch failed', ['status' => $response->status(), 'body' => $response->body()]);
            } else {
                $this->handleFcmResponse($response->json(), $tokens);
            }
        } catch (\Throwable $e) {
            Log::error('FCM HTTP error', ['error' => $e->getMessage()]);
        }
    }

    private function handleFcmResponse(array $result, array $tokens): void
    {
        if (empty($result['results'])) {
            return;
        }

        $invalidTokens = [];
        foreach ($result['results'] as $index => $res) {
            if (isset($res['error']) && in_array($res['error'], ['NotRegistered', 'InvalidRegistration'])) {
                $invalidTokens[] = $tokens[$index];
            }
        }

        if (! empty($invalidTokens)) {
            DeviceToken::whereIn('token', $invalidTokens)->delete();
            Log::info('FCM removed stale tokens', ['count' => count($invalidTokens)]);
        }
    }
}
