<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Tests\Marketing;

use CpCreation\VitiCore\Cart\Model\Cart;
use CpCreation\VitiCore\Marketing\Model\ProductReview;
use CpCreation\VitiCore\Marketing\Model\ProductReviewReport;
use CpCreation\VitiCore\Marketing\Model\ReviewInvitation;
use CpCreation\VitiCore\Product\Model\Product;
use PHPUnit\Framework\TestCase;

final class ProductReviewReportTest extends TestCase
{
    public function testPublishedReviewCanBeReportedAndResolvedWithoutBeingChanged(): void
    {
        $now = new \DateTimeImmutable('2026-07-23 10:00:00');
        $review = $this->createReview(true, $now);
        $report = new ProductReviewReport(
            $review,
            ProductReviewReport::REASON_INAPPROPRIATE,
            '  Certains termes doivent être vérifiés.  ',
            $now,
        );

        self::assertSame(ProductReviewReport::STATUS_OPEN, $report->getStatus());
        self::assertSame('Certains termes doivent être vérifiés.', $report->getComment());

        $report->resolve('  Contenu vérifié par la modération.  ', $now->modify('+1 hour'));

        self::assertSame(ProductReviewReport::STATUS_RESOLVED, $report->getStatus());
        self::assertSame('Contenu vérifié par la modération.', $report->getResolutionNote());
        self::assertEquals($now->modify('+1 hour'), $report->getResolvedAt());
        self::assertSame(ProductReview::STATUS_PUBLISHED, $review->getStatus());
    }

    public function testPendingReviewCannotBeReported(): void
    {
        $this->expectException(\DomainException::class);

        new ProductReviewReport(
            $this->createReview(false, new \DateTimeImmutable('2026-07-23 10:00:00')),
            ProductReviewReport::REASON_OTHER,
        );
    }

    public function testUnknownReasonIsRejected(): void
    {
        $this->expectException(\InvalidArgumentException::class);

        new ProductReviewReport(
            $this->createReview(true, new \DateTimeImmutable('2026-07-23 10:00:00')),
            'unknown',
        );
    }

    public function testProcessedReportCannotBeReplayedWithAnotherDecision(): void
    {
        $now = new \DateTimeImmutable('2026-07-23 10:00:00');
        $report = new ProductReviewReport(
            $this->createReview(true, $now),
            ProductReviewReport::REASON_OTHER,
        );
        $report->resolve('Décision initiale', $now);

        $this->expectException(\DomainException::class);

        $report->dismiss('Décision rejouée', $now->modify('+1 hour'));
    }

    private function createReview(bool $published, \DateTimeImmutable $now): ProductReview
    {
        $cart = new Cart();
        $cart->markFulfilled($now->modify('-10 days'));
        $invitation = new ReviewInvitation(
            $cart,
            'client@example.com',
            hash('sha256', 'token'),
            $now,
            $now->modify('+90 days'),
        );
        $invitation->markSent($now);

        return new ProductReview(
            invitation: $invitation,
            product: new Product(),
            cartItem: null,
            rating: 4,
            authorDisplayName: 'Jeanne',
            title: 'Belle découverte',
            comment: 'Une belle bouteille.',
            moderationRequired: !$published,
            submittedAt: $now,
        );
    }
}
