<?php

namespace App\Controller;

use App\Entity\CoastalPoint;
use App\Entity\PushSubscription;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/api/push', name: 'api_push_')]
class PushController extends AbstractController
{
    public function __construct(
        private EntityManagerInterface $em,
        private RateLimiterFactory $apiPushLimiter,
        #[Autowire('%env(VAPID_PUBLIC_KEY)%')] private string $vapidPublicKey,
    ) {}

    /**
     * GET /api/push/vapid-public-key
     * Retourne la clé publique VAPID pour l'abonnement push côté client.
     */
    #[Route('/vapid-public-key', name: 'vapid_key', methods: ['GET'])]
    public function vapidKey(): JsonResponse
    {
        return $this->json(['publicKey' => $this->vapidPublicKey]);
    }

    /**
     * POST /api/push/subscribe
     * Enregistre un abonnement push.
     *
     * {
     *   "endpoint": "https://...",
     *   "keys": { "auth": "...", "p256dh": "..." },
     *   "coastalPointId": "uuid"  // optionnel
     * }
     */
    #[Route('/subscribe', name: 'subscribe', methods: ['POST'])]
    public function subscribe(Request $request): JsonResponse
    {
        $limiter = $this->apiPushLimiter->create($request->getClientIp() ?? 'unknown');
        if (!$limiter->consume()->isAccepted()) {
            return $this->json(['error' => 'Too many requests'], 429);
        }

        $data = json_decode($request->getContent(), true);

        if (!isset($data['endpoint'], $data['keys']['auth'], $data['keys']['p256dh'])) {
            return $this->json(['error' => 'Missing required fields'], 422);
        }

        // Upsert : si l'endpoint existe déjà, on met à jour
        $repo = $this->em->getRepository(PushSubscription::class);
        $sub  = $repo->findOneBy(['endpoint' => $data['endpoint']]) ?? new PushSubscription();

        $sub->setEndpoint($data['endpoint']);
        $sub->setAuthToken($data['keys']['auth']);
        $sub->setP256dhKey($data['keys']['p256dh']);

        if (!empty($data['coastalPointId'])) {
            $spot = $this->em->getRepository(CoastalPoint::class)->find($data['coastalPointId']);
            $sub->setCoastalPoint($spot);
        }

        $this->em->persist($sub);
        $this->em->flush();

        return $this->json(['id' => (string) $sub->getId()], 201);
    }

    /**
     * DELETE /api/push/subscribe
     * Supprime un abonnement push.
     */
    #[Route('/subscribe', name: 'unsubscribe', methods: ['DELETE'])]
    public function unsubscribe(Request $request): JsonResponse
    {
        $data = json_decode($request->getContent(), true);
        if (empty($data['endpoint'])) {
            return $this->json(['error' => 'Missing endpoint'], 422);
        }

        $sub = $this->em->getRepository(PushSubscription::class)
            ->findOneBy(['endpoint' => $data['endpoint']]);

        if ($sub !== null) {
            $this->em->remove($sub);
            $this->em->flush();
        }

        return $this->json(null, 204);
    }
}
