<?php

namespace Tests\Feature;

use App\Services\ContentMigrationProcessor;
use Mtc\MercuryDataModels\Media;
use Tests\DatabaseTestCase;

/**
 * Mapping image values can be source URLs or media library ids since the edit
 * panel picks real media. These tests cover the resolver both directions.
 */
class ContentMigrationMediaValueTest extends DatabaseTestCase
{
    private ExposedContentMigrationProcessor $processor;

    protected function setUp(): void
    {
        parent::setUp();
        $this->processor = app(ExposedContentMigrationProcessor::class);
    }

    public function testResolvesMediaIdValues()
    {
        $media = Media::factory()->create(['src' => 'foo.png', 'type' => 'image']);

        $this->assertSame($media->id, $this->processor->exposedResolveImageValueToMediaId($media->id));
        $this->assertSame($media->id, $this->processor->exposedResolveImageValueToMediaId((string) $media->id));
    }

    public function testUnknownMediaIdResolvesToNull()
    {
        $this->assertNull($this->processor->exposedResolveImageValueToMediaId(999999999));
    }

    public function testUnwrapsSingleElementArrays()
    {
        $media = Media::factory()->create(['src' => 'foo.png', 'type' => 'image']);

        $this->assertSame($media->id, $this->processor->exposedResolveImageValueToMediaId([$media->id]));
    }

    public function testEmptyValuesResolveToNull()
    {
        $this->assertNull($this->processor->exposedResolveImageValueToMediaId(null));
        $this->assertNull($this->processor->exposedResolveImageValueToMediaId(''));
        $this->assertNull($this->processor->exposedResolveImageValueToMediaId([]));
    }

    public function testUrlValueReusesExistingImportBySourceFilename()
    {
        $url = 'https://origin.example/images/hero.jpg';
        $media = Media::factory()->create([
            'src' => 'imported/hero.jpg',
            'type' => 'image',
            'source_filename' => $url,
        ]);

        // Dedupe by source_filename means no new import (and no network call).
        $this->assertSame($media->id, $this->processor->exposedResolveImageValueToMediaId($url));
    }

    public function testBuildPreviewResolvesMediaIdImageValues()
    {
        $media = Media::factory()->create(['src' => 'foo.png', 'type' => 'image']);
        $structure = [
            [
                'name' => 'Hero',
                'fields' => [
                    ['slug' => 'image', 'name' => 'Image', 'type' => 'image', 'repeatable' => false],
                ],
            ],
        ];

        $preview = $this->processor->buildPreview(['Hero' => ['image' => $media->id]], $structure);

        $value = $preview[0]['fields'][0]['value'];
        $this->assertIsString($value);
        $this->assertStringNotContainsString('media:', $value);
    }

    public function testBuildPreviewLabelsMissingMedia()
    {
        $structure = [
            [
                'name' => 'Hero',
                'fields' => [
                    ['slug' => 'image', 'name' => 'Image', 'type' => 'image', 'repeatable' => false],
                ],
            ],
        ];

        $preview = $this->processor->buildPreview(['Hero' => ['image' => 999999999]], $structure);

        $this->assertSame('media:999999999', $preview[0]['fields'][0]['value']);
    }

    public function testBuildPreviewKeepsUrlValuesAndListCardinality()
    {
        $structure = [
            [
                'name' => 'Gallery',
                'fields' => [
                    ['slug' => 'images', 'name' => 'Images', 'type' => 'image', 'repeatable' => false],
                ],
            ],
        ];
        $media = Media::factory()->create(['src' => 'foo.png', 'type' => 'image']);

        $preview = $this->processor->buildPreview(
            ['Gallery' => ['images' => ['https://origin.example/a.jpg', $media->id]]],
            $structure,
        );

        $value = $preview[0]['fields'][0]['value'];
        $this->assertIsArray($value);
        $this->assertSame('https://origin.example/a.jpg', $value[0]);
        $this->assertIsString($value[1]);
    }
}

/**
 * Test double exposing the protected image-value resolver.
 */
class ExposedContentMigrationProcessor extends ContentMigrationProcessor
{
    public function exposedResolveImageValueToMediaId(mixed $value): ?int
    {
        return $this->resolveImageValueToMediaId($value);
    }
}
