<?php

namespace apexl\Io\modules\user\controllers;

use apexl\hashing\Hash;
use apexl\Io\factories\MailerFactory;
use apexl\Io\includes\Controller;
use apexl\Io\includes\RouteManager;
use apexl\Io\modules\email\services\TemplateService;
use apexl\Io\modules\user\entities\userEntity;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

final readonly class ForgotPasswordController extends Controller
{
    public function __invoke(
        MailerFactory $mailerFactory,
        TemplateService $templateService,
        RouteManager $routeManager,
        ServerRequestInterface $request,
        ResponseInterface $response
    ): ResponseInterface {
        $body = (object) $request->getParsedBody();
        //first, grab the user data.
        $user = userEntity::from('email', $body->email);

        //got a match? we need to generate a new random hash, then email it to the user.
        if (!!$user) {
            $hash = new Hash();
            //we do this so the has can be passed back as a url param rather than a query string.
            $randomHash = str_replace('/', '@', $hash->generateRandomHash());
            //write the hash to the database
            $user->newForgottenPasswordLink($randomHash);
            //now we send email to the user.
            $this->forgottenPasswordEmail(
                $mailerFactory,
                $templateService,
                $user->first_name,
                $user->email,
                $routeManager->getRoutePattern('user.display.reset-password', ['hash' => $randomHash])
            );
            $this->output->addMetadata(
                'user.forgot-password.redirect',
                'redirect',
                $routeManager->getRoutePattern('user.display.forgot-password.check-email')
            );
        } else {
            $this->output->addMessage('user.forgot-password', 'error', 'User account does not exist');
        }
        $this->output->addResponse($request); //added so we can hook into this elsewhere.

        return $this->json($response);
    }

    protected function forgottenPasswordEmail(MailerFactory $mailerFactory, TemplateService $templateService, string $firstName, string $email, string $link): void
    {
        /**
         * @TODO Allow for database config here.
         * @TODO Move all this to the central mailer system, make an easy to use mailer function
         */
        $from = config('app.site.email_address') ?? 'no-reply@localhost.com';
        $fromName = config('app.site.name') ?? 'localhost';
        $frontEndDomain = config('app.site.frontend_domain') ?? 'localhost';

        /** @TODO Move to config. * */
        //$link = rtrim((string) $frontEndDomain, '/').'/api/v1/user/data/forgot-password/h/'.$string;
        $link = rtrim($frontEndDomain, '/') . '/' . ltrim('/' . $link, '/');

        try {
            $mailer = $mailerFactory->make();
            $mailer->setFrom($from, $fromName);
            $mailer->addAddress($email);     // Add a recipient

            $mailer->Subject = 'Password Reset Request';
            $mailer->Body = $templateService->fetch('password_reset', [
                'from_name' => $fromName,
                'reset_link' => $link,
                'name' => $firstName,
            ]);
            $mailer->IsHTML();
            $mailer->send();
        } catch (\PHPMailer\PHPMailer\Exception $e) {
            user_error(
                sprintf('Unable to send forgot password email: %s', $e->getMessage()),
                E_USER_WARNING
            );
        }
    }
}
