<?php

namespace Functional\Users\Http\Controllers;

use Functional\Streaks\Models\Streak;
use Functional\Users\Http\Requests\LoginRequest;
use Functional\Users\Http\Requests\RegisterRequest;
use Functional\Users\Http\Requests\UpdateProfileRequest;
use Functional\Users\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;

/**
 * Auth par cookie de session Sanctum SPA (inscription + login mot de passe). Le front n'a aucune
 * logique d'auth : il POST ces routes et affiche ce qui revient.
 */
class AuthController
{
    /**
     * Inscription par mot de passe : crée le user, son streak vide, ouvre la session.
     */
    public function register(RegisterRequest $request): JsonResponse
    {
        $user = User::create([
            'name' => $request->validated('name'),
            'email' => $request->validated('email'),
            'password' => $request->validated('password'),
        ]);

        Streak::firstOrCreate(['user_id' => $user->id]);

        Auth::login($user);

        $request->session()->regenerate();

        return response()->json(['user' => $user], Response::HTTP_CREATED);
    }

    /**
     * Login par mot de passe : la validation des identifiants vit dans LoginRequest::authenticate().
     */
    public function login(LoginRequest $request): JsonResponse
    {
        $request->authenticate();

        return response()->json(['user' => $request->user()]);
    }

    /**
     * Ferme la session et invalide le cookie ; nécessite d'être authentifié (middleware `auth`).
     */
    public function logout(Request $request): Response
    {
        Auth::guard('web')->logout();

        $request->session()->invalidate();
        $request->session()->regenerateToken();

        return response()->noContent();
    }

    /**
     * Vue "prête à afficher" du profil courant + résumé du streak, consommée par /api/me.
     */
    public function me(Request $request): JsonResponse
    {
        /** @var User $user */
        $user = $request->user();

        $streak = Streak::firstOrCreate(['user_id' => $user->id]);

        return response()->json([
            'user' => [
                'id' => $user->id,
                'name' => $user->name,
                'email' => $user->email,
                'locale' => $user->locale,
                'units' => $user->units,
                'timezone' => $user->timezone,
                'avatar_url' => $this->avatarUrl($user->avatar_path),
                'available_equipment' => $user->available_equipment ?? [],
            ],
            'streak' => [
                'current' => $streak->current_count,
                'longest' => $streak->longest_count,
                'freezes' => $streak->freezes_available,
            ],
            'push' => [
                'vapid_public_key' => config('webpush.vapid.public_key'),
                'enabled' => $user->pushSubscriptions()->exists(),
            ],
        ]);
    }

    /**
     * PATCH /api/me — met à jour les préférences du profil courant (matériel possédé, locale, unités…).
     * Renvoie la vue /api/me rafraîchie.
     */
    public function update(UpdateProfileRequest $request): JsonResponse
    {
        $request->user()->update($request->validated());

        return $this->me($request);
    }

    /**
     * Résout l'URL publique d'un média stocké sur RustFS/S3 à partir de son chemin relatif.
     */
    private function avatarUrl(?string $avatarPath): ?string
    {
        if (! $avatarPath) {
            return null;
        }

        return rtrim((string) config('services.media.base_url'), '/') . '/' . ltrim($avatarPath, '/');
    }
}
