<?php

declare(strict_types=1);

namespace Apexl\Io\User\Actions;

use Apexl\Config\Exceptions\MissingConfigException;
use Apexl\Hashing\Hash;
use Apexl\Io\Exceptions\RouteNotFoundException;
use Apexl\Io\Notifier\Exceptions\NotifierException;
use Apexl\Io\Notifier\Factories\NotifierFactory;
use Apexl\Io\Services\HttpPaths;
use Apexl\Io\Services\RouteUrls;
use Apexl\Io\User\Entities\UserEntity;
use Apexl\Io\User\Factories\ForgotPasswordLinkFactory;
use Apexl\Io\User\Notifiers\ResetPasswordEmailNotifier;

final readonly class ForgotPasswordAction
{
    public function __construct(
        private HttpPaths $httpPaths,
        private NotifierFactory $notifierFactory,
        private ForgotPasswordLinkFactory $forgotPasswordLinkService,
        private RouteUrls $routeUrls,
        private Hash $hash,
    ) {}

    /**
     * @throws MissingConfigException
     * @throws RouteNotFoundException
     * @throws NotifierException
     */
    public function handle(UserEntity $user): void
    {
        $this->notifierFactory->make(ResetPasswordEmailNotifier::class, [
            'user' => $user,
            'link' => $this->link($user),
        ])->send();
    }

    /**
     * @throws MissingConfigException
     * @throws RouteNotFoundException
     */
    private function link(UserEntity $user): string
    {
        //we do this so the hash can be passed back as a url param rather than a query string.
        $randomHash = str_replace('/', '@', $this->hash->generateRandomHash());
        //write the hash to the database
        $this->forgotPasswordLinkService->create($user->email, $randomHash);

        return $this->httpPaths->frontendUrl(
            $this->routeUrls->url('user.display.reset-password', ['hash' => $randomHash])
        );
    }
}