<?php

namespace Tests\Tenant;

use App\Imports\AutoGrabToVehicleImport;
use Mtc\MercuryDataModels\Media;
use Mtc\MercuryDataModels\Vehicle;
use ReflectionMethod;
use Tests\TenantTestCase;

class AutoGrabImageSyncTest extends TenantTestCase
{
    private function syncImages(Vehicle $vehicle, array $urls): void
    {
        $import = new AutoGrabToVehicleImport();
        (new ReflectionMethod($import, 'syncImages'))->invoke($import, $vehicle, $urls);
    }

    public function testReSyncingTheSameImagesDoesNotChurnMediaUses(): void
    {
        $vehicle = Vehicle::factory()->create();

        $this->syncImages($vehicle, ['a.jpg', 'b.jpg']);
        $useIdsBefore = $vehicle->mediaUses()->orderBy('id')->pluck('id')->all();
        $this->assertCount(2, $useIdsBefore);

        // An identical snapshot should be a no-op: the same use rows survive untouched.
        $this->syncImages($vehicle, ['a.jpg', 'b.jpg']);
        $useIdsAfter = $vehicle->mediaUses()->orderBy('id')->pluck('id')->all();

        $this->assertSame($useIdsBefore, $useIdsAfter);
        $this->assertSame(2, Media::query()->where('image_provider', 'autograb')->count());
    }

    public function testSyncOnlyAddsAndRemovesTheDifference(): void
    {
        $vehicle = Vehicle::factory()->create();

        $this->syncImages($vehicle, ['a.jpg', 'b.jpg']);
        $keptUseId = $vehicle->mediaUses()
            ->whereHas('media', fn ($query) => $query->where('src', 'a.jpg'))
            ->value('id');

        // Drop b.jpg, add c.jpg.
        $this->syncImages($vehicle, ['a.jpg', 'c.jpg']);

        $srcs = $vehicle->mediaUses()->with('media')->get()
            ->map(fn ($use) => $use->media->src)
            ->sort()
            ->values()
            ->all();
        $this->assertSame(['a.jpg', 'c.jpg'], $srcs);

        // a.jpg's use row is reused, not recreated.
        $this->assertSame(
            $keptUseId,
            $vehicle->mediaUses()
                ->whereHas('media', fn ($query) => $query->where('src', 'a.jpg'))
                ->value('id')
        );

        // b.jpg was only used by this vehicle, so its media record is removed as an orphan.
        $this->assertNull(Media::query()->where('src', 'b.jpg')->first());
    }

    public function testRemovedImageMediaIsKeptWhenAnotherModelStillUsesIt(): void
    {
        $vehicleOne = Vehicle::factory()->create();
        $vehicleTwo = Vehicle::factory()->create();

        $this->syncImages($vehicleOne, ['shared.jpg']);
        $this->syncImages($vehicleTwo, ['shared.jpg']);

        // Remove the shared image from the first vehicle only.
        $this->syncImages($vehicleOne, ['other.jpg']);

        // The media is still referenced by vehicle two, so it must not be deleted.
        $this->assertNotNull(Media::query()->where('src', 'shared.jpg')->first());
        $this->assertSame(0, $vehicleOne->mediaUses()
            ->whereHas('media', fn ($query) => $query->where('src', 'shared.jpg'))
            ->count());
        $this->assertSame(1, $vehicleTwo->mediaUses()
            ->whereHas('media', fn ($query) => $query->where('src', 'shared.jpg'))
            ->count());
    }
}
