<?php

declare(strict_types=1);

namespace App\Controller;

use App\Repository\ProfileRepository;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Symfony\Component\Routing\Attribute\Route;

final class SessionProfileController
{
    public function __construct(
        private readonly ProfileRepository $profiles,
        private readonly UserPasswordHasherInterface $passwordHasher,
        #[Autowire(service: 'limiter.login')]
        private readonly RateLimiterFactory $loginLimiter,
    ) {}

    #[Route('/api/session/profile', name: 'api_session_profile_get', methods: ['GET'])]
    public function getActiveProfile(Request $request): JsonResponse
    {
        $session = $request->getSession();
        if (!$session instanceof SessionInterface) {
            return new JsonResponse(['message' => 'Session indisponible.'], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
        }

        $profileId = $session->get('profileId');
        if (!$profileId) {
            return new JsonResponse(['message' => 'Aucun profil actif.'], JsonResponse::HTTP_UNAUTHORIZED);
        }

        $profile = $this->profiles->find($profileId);
        if (!$profile || !$profile->isActive()) {
            $session->remove('profileId');

            return new JsonResponse(['message' => 'Profil introuvable ou inactif.'], JsonResponse::HTTP_UNAUTHORIZED);
        }

        return new JsonResponse([
            'id'        => $profile->getId(),
            'firstName' => $profile->getFirstName(),
            'lastName'  => $profile->getLastName(),
            'email'     => $profile->getEmail(),
            'isActive'  => $profile->isActive(),
            'roles'     => $profile->getRoles(),
        ]);
    }

    #[Route('/api/session/profile', name: 'api_session_profile_post', methods: ['POST'])]
    public function activateProfile(Request $request): JsonResponse
    {
        $session = $request->getSession();
        if (!$session instanceof SessionInterface) {
            return new JsonResponse(['message' => 'Session indisponible.'], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
        }

        $limiter = $this->loginLimiter->create($request->getClientIp());
        if (!$limiter->consume()->isAccepted()) {
            return new JsonResponse(['message' => 'Trop de tentatives. Réessayez dans une minute.'], JsonResponse::HTTP_TOO_MANY_REQUESTS);
        }

        $payload   = $request->toArray();
        $profileId = $payload['profileId'] ?? null;

        if (!$profileId) {
            return new JsonResponse(['message' => 'profileId est requis.'], JsonResponse::HTTP_BAD_REQUEST);
        }

        $profile = $this->profiles->find($profileId);

        $password = $payload['password'] ?? '';
        if ('' === $password) {
            return new JsonResponse(['message' => 'Mot de passe requis.'], JsonResponse::HTTP_BAD_REQUEST);
        }

        $loginFailed = new JsonResponse(['message' => 'Identifiants invalides.'], JsonResponse::HTTP_UNAUTHORIZED);

        if (!$profile || !$profile->isActive()) {
            return $loginFailed;
        }

        if (!$profile->getPassword()) {
            return $loginFailed;
        }

        if (!$this->passwordHasher->isPasswordValid($profile, $password)) {
            return $loginFailed;
        }

        $session->migrate(true);
        $session->set('profileId', $profile->getId());
        $session->set('profileRoles', $profile->getRoles());

        return new JsonResponse([
            'id'        => $profile->getId(),
            'firstName' => $profile->getFirstName(),
            'lastName'  => $profile->getLastName(),
            'email'     => $profile->getEmail(),
            'isActive'  => $profile->isActive(),
            'roles'     => $profile->getRoles(),
        ]);
    }

    #[Route('/api/session/profile', name: 'api_session_profile_delete', methods: ['DELETE'])]
    public function logout(Request $request): JsonResponse
    {
        $session = $request->getSession();
        if ($session instanceof SessionInterface) {
            $session->invalidate();
        }

        return new JsonResponse(['success' => true]);
    }
}
