<?php

namespace Tests\Unit\Services;

use App\Http\Integrations\Spotify\SpotifyClient;
use App\Models\Album;
use App\Models\Artist;
use App\Services\SpotifyService;
use Illuminate\Support\Facades\File;
use Mockery;
use Mockery\LegacyMockInterface;
use Mockery\MockInterface;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

use function Tests\test_path;

class SpotifyServiceTest extends TestCase
{
    private SpotifyService $service;
    private SpotifyClient|MockInterface|LegacyMockInterface $client;

    public function setUp(): void
    {
        parent::setUp();

        config([
            'koel.spotify.client_id' => 'fake-client-id',
            'koel.spotify.client_secret' => 'fake-client-secret',
        ]);

        $this->client = Mockery::mock(SpotifyClient::class);
        $this->service = new SpotifyService($this->client);
    }

    #[Test]
    public function tryGetArtistImage(): void
    {
        /** @var Artist $artist */
        $artist = Artist::factory(['name' => 'Foo'])->create();

        $this->client
            ->shouldReceive('search')
            ->with('Foo', 'artist', ['limit' => 1])
            ->andReturn(self::parseFixture('search-artist.json'));

        self::assertSame('https://foo/bar.jpg', $this->service->tryGetArtistImage($artist));
    }

    #[Test]
    public function tryGetArtistImageWhenServiceIsNotEnabled(): void
    {
        config(['koel.spotify.client_id' => null]);

        $this->client->shouldNotReceive('search');

        self::assertNull($this->service->tryGetArtistImage(Mockery::mock(Artist::class)));
    }

    #[Test]
    public function tryGetAlbumImage(): void
    {
        /** @var Album $album */
        $album = Album::factory(['name' => 'Bar'])->for(Artist::factory(['name' => 'Foo']))->create();

        $this->client
            ->shouldReceive('search')
            ->with('Bar artist:Foo', 'album', ['limit' => 1])
            ->andReturn(self::parseFixture('search-album.json'));

        self::assertSame('https://foo/bar.jpg', $this->service->tryGetAlbumCover($album));
    }

    #[Test]
    public function tryGetAlbumImageWhenServiceIsNotEnabled(): void
    {
        config(['koel.spotify.client_id' => null]);

        $this->client->shouldNotReceive('search');

        self::assertNull($this->service->tryGetAlbumCover(Mockery::mock(Album::class)));
    }

    /** @return array<mixed> */
    private static function parseFixture(string $name): array
    {
        return json_decode(File::get(test_path("blobs/spotify/$name")), true);
    }

    protected function tearDown(): void
    {
        config([
            'koel.spotify.client_id' => null,
            'koel.spotify.client_secret' => null,
        ]);

        parent::tearDown();
    }
}
