<?php

namespace Tests\Feature;

use App\Models\PlatformInstance;
use App\Services\Platform\CommunityDirectory;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;

class CommunityDirectoryTest extends TestCase
{
    use RefreshDatabase;

    private PlatformInstance $instance;

    protected function setUp(): void
    {
        parent::setUp();
        Cache::flush();
        $this->instance = PlatformInstance::factory()->create(['url' => 'https://lemmy.test']);

        Http::fake(['*/api/v3/community/list*' => Http::response([
            'communities' => [
                ['community' => ['id' => 8, 'name' => 'news', 'title' => 'News']],
                ['community' => ['id' => 42, 'name' => '42', 'title' => 'Forty Two']],
            ],
        ])]);
    }

    private function directory(): CommunityDirectory
    {
        return app(CommunityDirectory::class);
    }

    public function test_it_fetches_communities_for_an_instance(): void
    {
        $this->assertSame([42, 8], collect($this->directory()->forInstance($this->instance))->pluck('id')->all());
    }

    public function test_it_only_calls_the_instance_once_per_cache_window(): void
    {
        $this->directory()->forInstance($this->instance);
        $this->directory()->forInstance($this->instance);

        Http::assertSentCount(1);
    }

    public function test_forget_causes_a_refetch(): void
    {
        $this->directory()->forInstance($this->instance);
        $this->directory()->forget($this->instance);
        $this->directory()->forInstance($this->instance);

        Http::assertSentCount(2);
    }

    public function test_it_caches_per_instance(): void
    {
        $other = PlatformInstance::factory()->create(['url' => 'https://other.test']);

        $this->directory()->forInstance($this->instance);
        $this->directory()->forInstance($other);

        Http::assertSentCount(2);
    }

    public function test_has_reports_membership(): void
    {
        $this->assertTrue($this->directory()->has($this->instance, 8));
        $this->assertFalse($this->directory()->has($this->instance, 4242));
    }

    public function test_a_numerically_named_community_keeps_its_own_id(): void
    {
        // The community is named "42" but its id is also 42 by coincidence; the
        // name must never be read as an id.
        $this->assertSame('42', $this->directory()->name($this->instance, 42));
        $this->assertTrue($this->directory()->has($this->instance, 42));
    }
}
