<?php

declare(strict_types=1);

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Controller\Site;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Form\Site\ProductReviewReportType;
use CpCreation\VitiCore\Marketing\DTO\ProductReviewReportSubmission;
use CpCreation\VitiCore\Marketing\Model\ProductReview;
use CpCreation\VitiCore\Marketing\Model\ProductReviewReport;
use CpCreation\VitiCore\Marketing\Repository\ProductReviewReportRepository;
use CpCreation\VitiCore\Marketing\ReviewPublicationPolicy;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Symfony\Contracts\Translation\TranslatorInterface;

final class ProductReviewReportController extends AbstractController
{
    public function __construct(
        private readonly ProductReviewReportRepository $reportRepository,
        private readonly ReviewPublicationPolicy $publicationPolicy,
        private readonly RateLimiterFactory $productReviewReportsLimiter,
        private readonly TranslatorInterface $translator,
    ) {}

    public function report(Request $request, ProductReview $review): Response
    {
        if (!$this->publicationPolicy->isPublic($review)) {
            throw $this->createNotFoundException();
        }
        $sessionKey = 'marketing.review_reported.' . $review->getId()->toString();
        $alreadyReported = $request->getSession()->get($sessionKey, false);
        if ($request->isMethod('POST') && true === $alreadyReported) {
            return $this->redirectToRoute('shop_product_review_report', [
                '_locale' => $request->getLocale(),
                'id' => $review->getId()->toString(),
            ]);
        }
        if ($request->isMethod('POST')) {
            $limit = $this->productReviewReportsLimiter
                ->create(hash('sha256', (string) $request->getClientIp()))
                ->consume()
            ;
            if (!$limit->isAccepted()) {
                $retryAfter = max(1, $limit->getRetryAfter()->getTimestamp() - time());

                throw new TooManyRequestsHttpException($retryAfter);
            }
        }

        $submission = new ProductReviewReportSubmission();
        $form = $this->createForm(ProductReviewReportType::class, $submission);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            /** @var ProductReviewReportSubmission $submission */
            $submission = $form->getData();
            $this->reportRepository->save(new ProductReviewReport(
                $review,
                $submission->reason,
                $submission->comment,
            ));
            $request->getSession()->set($sessionKey, true);
            $this->addFlash('review-report-success', $this->translator->trans('marketing.review_report.form.saved'));

            return $this->redirectToRoute('shop_product_review_report', [
                '_locale' => $request->getLocale(),
                'id' => $review->getId()->toString(),
            ]);
        }

        return $this->render('@CpCreationVitiCore/marketing/review/report.html.twig', [
            'review' => $review,
            'form' => $form->createView(),
            'already_reported' => true === $alreadyReported,
        ]);
    }
}
