<?php

namespace App\Controllers;

use App\Auth\UseCases\AuthenticateUser\AuthenticateUser;
use App\Auth\UseCases\AuthenticateUser\AuthenticateUserRequest;
use App\Auth\UseCases\CreateSession\CreateSession;
use App\Auth\UseCases\Logout\Logout;
use App\Exceptions\BadRequestException;
use App\Exceptions\UnauthorizedException;
use App\Http\Middleware\AuthMiddleware;
use App\User\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Cookie;

class AuthController
{
    public function __construct(
        private AuthenticateUser $authenticateUser,
        private CreateSession $createSession,
        private Logout $logout,
    ) {
    }

    public function login(Request $request): JsonResponse
    {
        try {
            $user = $this->authenticateUser->execute(
                new AuthenticateUserRequest(
                    email: $request->input('email'),
                    password: $request->input('password'),
                )
            );
        } catch (BadRequestException $exception) {
            return new JsonResponse(
                ['error' => $exception->getMessage()],
                400
            );
        } catch (UnauthorizedException $exception) {
            return new JsonResponse(
                ['error' => $exception->getMessage()],
                401
            );
        }

        $session = $this->createSession->execute($user);

        $response = new JsonResponse([
            'user' => $this->buildUserPayload($user),
        ], 200);

        return $response->withCookie(Cookie::create(
            name: AuthMiddleware::COOKIE_NAME,
            value: $session->getToken(),
            expire: $session->getExpiresAt()->getTimestamp(),
            path: '/',
            domain: null,
            secure: false,
            httpOnly: true,
            raw: false,
            sameSite: Cookie::SAMESITE_LAX,
        ));
    }

    public function me(Request $request): JsonResponse
    {
        /** @var User $user */
        $user = $request->attributes->get('user');

        return new JsonResponse([
            'user' => $this->buildUserPayload($user),
        ], 200);
    }

    /**
     * @return array{id: int, email: string}
     */
    private function buildUserPayload(User $user): array
    {
        return [
            'id' => $user->getId(),
            'email' => $user->getEmail()->value(),
        ];
    }

    public function logout(Request $request): JsonResponse
    {
        $token = $request->cookie(AuthMiddleware::COOKIE_NAME);
        if (is_string($token) && $token !== '') {
            $this->logout->execute($token);
        }

        $response = new JsonResponse(null, 204);

        return $response->withCookie(Cookie::create(
            name: AuthMiddleware::COOKIE_NAME,
            value: '',
            expire: 1,
            path: '/',
            domain: null,
            secure: false,
            httpOnly: true,
            raw: false,
            sameSite: Cookie::SAMESITE_LAX,
        ));
    }
}
