<?php

namespace App\Http\Controllers\Portal;

use App\Domain\Shared\Models\DeviceToken;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/**
 * Registers a browser's (or the native shell's) FCM token against the signed-in
 * account.
 *
 * This is a session-authenticated web route with CSRF, not an API endpoint. The
 * portal is session-authenticated and the Flutter shell carries the portal's
 * own cookie, so there is nothing for a second identity system to do here.
 *
 * The row is keyed on (device_token, user_id) — never on the token alone. The
 * deleted API keyed on the token by itself, so anyone could claim anyone's
 * token and the victim's phone would then receive the attacker's
 * notifications.
 */
class DeviceTokenController extends Controller
{
    public function store(Request $request): JsonResponse
    {
        $data = $request->validate([
            'token' => ['required', 'string', 'min:20', 'max:512'],
            'platform' => ['required', 'in:web,android,ios'],
            'device_name' => ['nullable', 'string', 'max:120'],
            'app_version' => ['nullable', 'string', 'max:40'],
        ]);

        $user = $request->user();

        // Someone else holding this exact token means the device changed hands
        // or the browser profile was copied. The old claim goes, rather than
        // both accounts receiving each other's notifications.
        DeviceToken::withoutGlobalScopes()
            ->where('device_token', $data['token'])
            ->where('user_id', '!=', $user->id)
            ->delete();

        DeviceToken::withoutGlobalScopes()->updateOrCreate(
            ['device_token' => $data['token'], 'user_id' => $user->id],
            [
                'academy_id' => $user->academy_id,
                'platform' => $data['platform'],
                'device_name' => $data['device_name'] ?? null,
                'user_agent' => substr((string) $request->userAgent(), 0, 255),
                'app_version' => $data['app_version'] ?? null,
                'is_active' => true,
                'last_used_at' => now(),
            ]
        );

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

    public function destroy(Request $request): JsonResponse
    {
        $data = $request->validate([
            'token' => ['required', 'string', 'max:512'],
        ]);

        DeviceToken::withoutGlobalScopes()
            ->where('device_token', $data['token'])
            ->where('user_id', $request->user()->id)
            ->delete();

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

    /**
     * The Firebase web config the portal needs to obtain a token at all.
     *
     * Every value here is public by design — a Firebase web config is embedded
     * in any site that uses it, and delivery is authorised by the token, not by
     * the config. It is served per tenant because each client has their own
     * Firebase project.
     */
    public function config(Request $request): JsonResponse
    {
        $settings = app(\App\Domain\Shared\Services\SettingsService::class);

        $config = [
            'apiKey' => $settings->get('mobile_app.firebase_web_api_key'),
            'projectId' => $settings->get('mobile_app.firebase_project_id'),
            'messagingSenderId' => $settings->get('mobile_app.firebase_sender_id'),
            'appId' => $settings->get('mobile_app.firebase_web_app_id'),
            'vapidKey' => $settings->get('mobile_app.firebase_vapid_public_key'),
        ];

        // Half-configured is worse than unconfigured: the SDK throws on init and
        // takes the page with it.
        $configured = ! in_array(null, $config, true) && ! in_array('', $config, true);

        return response()->json([
            'configured' => $configured,
            'config' => $configured ? $config : null,
        ])->header('Cache-Control', 'private, no-store');
    }
}
