<?php

namespace Modules\PortalApi\Http\Controllers\Api;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\PortalApi\Entities\PortalOwner;
use Modules\PortalApi\Entities\PortalPushSubscription;

class PushController extends Controller
{
    /** Public — the PWA fetches this before calling pushManager.subscribe(). */
    public function vapidKey(): JsonResponse
    {
        $key = config('portal_push.public_key');
        if (! $key) {
            return response()->json([
                'message' => 'Push notifications are not configured for this server.',
            ], 503);
        }
        return response()->json(['public_key' => $key]);
    }

    /**
     * Save (or upsert) a subscription. The PWA POSTs the object returned by
     * the browser's pushManager.subscribe() — endpoint URL + keys + optional
     * per-category preferences.
     */
    public function subscribe(Request $request): JsonResponse
    {
        $data = $request->validate([
            'endpoint'       => 'required|url|max:500',
            'keys.p256dh'    => 'required|string|max:191',
            'keys.auth'      => 'required|string|max:64',
            'categories'     => 'nullable|array',
            'categories.*'   => 'in:' . implode(',', PortalPushSubscription::CATEGORIES),
        ]);

        /** @var PortalOwner $owner */
        $owner = $request->attributes->get('portal_owner');
        if (! $owner instanceof PortalOwner) {
            return response()->json(['message' => 'Unauthenticated'], 401);
        }

        $sub = PortalPushSubscription::updateOrCreate(
            ['owner_id' => $owner->id, 'endpoint' => $data['endpoint']],
            [
                'p256dh_key'           => $data['keys']['p256dh'],
                'auth_key'             => $data['keys']['auth'],
                'user_agent'           => $request->userAgent(),
                'categories'           => $data['categories'] ?? PortalPushSubscription::CATEGORIES,
                'consecutive_failures' => 0,
            ]
        );

        return response()->json([
            'id'         => $sub->id,
            'categories' => $sub->categories,
        ], 200);
    }

    /** Toggle which categories an existing subscription receives. */
    public function preferences(Request $request): JsonResponse
    {
        $data = $request->validate([
            'endpoint'     => 'required|url',
            'categories'   => 'required|array',
            'categories.*' => 'in:' . implode(',', PortalPushSubscription::CATEGORIES),
        ]);

        /** @var PortalOwner $owner */
        $owner = $request->attributes->get('portal_owner');
        $sub = PortalPushSubscription::where('owner_id', $owner->id)
            ->where('endpoint', $data['endpoint'])
            ->first();
        if (! $sub) {
            return response()->json(['message' => 'Subscription not found.'], 404);
        }

        $sub->forceFill(['categories' => $data['categories']])->save();
        return response()->json(['categories' => $sub->categories]);
    }

    public function unsubscribe(Request $request): JsonResponse
    {
        $data = $request->validate(['endpoint' => 'required|url']);

        /** @var PortalOwner $owner */
        $owner = $request->attributes->get('portal_owner');
        PortalPushSubscription::where('owner_id', $owner->id)
            ->where('endpoint', $data['endpoint'])
            ->delete();

        return response()->json(['ok' => true]);
    }
}
