<?php

namespace App\Tests\Blog;

use App\Auth\Entity\User;
use App\Blog\Entity\Blog;
use App\Blog\Service\BlogCacheInvalidator;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * باطل‌سازی کش ISR سایت عمومی پس از هر نوشتن روی بلاگ.
 * fail-open است: شکست شبکه نباید ذخیرهٔ مقاله را بشکند.
 */
class BlogCacheInvalidatorTest extends TestCase
{
    private function makeBlog(): Blog
    {
        return new Blog(new User('09120000000'), 'عنوان آزمایشی', 'متن آزمایشی مقاله');
    }

    /** @param list<array{0:string,1:string,2:array}> $calls */
    private function recordingClient(array &$calls, int $status = 200): HttpClientInterface
    {
        return new MockHttpClient(function (string $method, string $url, array $options) use (&$calls, $status) {
            $calls[] = [$method, $url, $options];

            return new MockResponse('{"revalidated":true}', ['http_code' => $status]);
        });
    }

    public function testSendsTagsForSlugUuidAndList(): void
    {
        $calls = [];
        $blog  = $this->makeBlog();

        (new BlogCacheInvalidator(
            $this->recordingClient($calls),
            new NullLogger(),
            'https://nobat724.com/api/revalidate',
            's3cret',
        ))->invalidate($blog);

        self::assertCount(1, $calls);
        [$method, $url, $options] = $calls[0];
        self::assertSame('POST', $method);
        self::assertSame('https://nobat724.com/api/revalidate', $url);
        self::assertContains('X-Revalidate-Secret: s3cret', $options['headers']);

        $body = json_decode($options['body'], true);
        self::assertSame(
            ['blog-' . $blog->getSlug(), 'blog-' . $blog->getUuid(), 'blog-list'],
            $body['tags']
        );
    }

    public function testNetworkFailureIsSwallowed(): void
    {
        $client = new MockHttpClient(function (): MockResponse {
            throw new class ('boom') extends \RuntimeException implements TransportExceptionInterface {};
        });

        $invalidator = new BlogCacheInvalidator($client, new NullLogger(), 'https://nobat724.com/api/revalidate', 's3cret');

        $invalidator->invalidate($this->makeBlog());
        self::assertTrue(true, 'شکست شبکه نباید exception بدهد');
    }

    public function testNoRequestWhenWebhookIsNotConfigured(): void
    {
        $calls = [];

        // URL خالی — محیط dev/تست بدون سایت عمومی
        (new BlogCacheInvalidator($this->recordingClient($calls), new NullLogger(), '', 's3cret'))
            ->invalidate($this->makeBlog());
        // سکرت خالی — پیکربندی ناقص نباید درخواست بدون احراز بفرستد
        (new BlogCacheInvalidator($this->recordingClient($calls), new NullLogger(), 'https://nobat724.com/api/revalidate', ''))
            ->invalidate($this->makeBlog());

        self::assertSame([], $calls);
    }
}
