<?php

declare(strict_types=1);

namespace App\Tests\Api\Service;

use App\DTO\SyncConfirmation;
use App\Enum\ModelCategory;
use App\Service\Sync\ProductSyncStrategy;
use App\Tests\AbstractApiTestCase;

/**
 * @internal
 */
class ProductSyncStrategyTest extends AbstractApiTestCase
{
    private ProductSyncStrategy $strategy;

    protected function setUp(): void
    {
        parent::setUp();
        $this->strategy = static::getContainer()->get(ProductSyncStrategy::class);
    }

    public function testSupportsProductCategory(): void
    {
        $mt = $this->createModelType('Product Cat', 'PC-001', ModelCategory::PRODUCT);
        $this->assertTrue($this->strategy->supports($mt));
    }

    public function testDoesNotSupportComponentCategory(): void
    {
        $mt = $this->createModelType('Comp Cat', 'CC-001', ModelCategory::COMPONENT);
        $this->assertFalse($this->strategy->supports($mt));
    }

    public function testPreviewNoImpactWhenNoProducts(): void
    {
        $mt     = $this->createModelType('Product Cat', 'PC-001', ModelCategory::PRODUCT);
        $result = $this->strategy->preview($mt, ['customFields' => []]);
        $this->assertSame(0, $result->itemCount);
        $this->assertFalse($result->hasImpact());
    }

    public function testPreviewDetectsNewCustomField(): void
    {
        $mt = $this->createModelType('Product Cat', 'PC-001', ModelCategory::PRODUCT);
        $this->createProduct('P1', 'P1-REF', $mt);

        $result = $this->strategy->preview($mt, [
            'customFields' => [
                ['name' => 'Weight', 'type' => 'text', 'orderIndex' => 0],
            ],
        ]);

        $this->assertSame(1, $result->itemCount);
        $this->assertSame(1, $result->additions['customFieldValues']);
    }

    public function testExecuteCreatesCustomFieldValues(): void
    {
        $mt      = $this->createModelType('Product Cat', 'PC-001', ModelCategory::PRODUCT);
        $product = $this->createProduct('P1', 'P1-REF', $mt);

        // Create a custom field on the model type
        $this->createCustomField('Weight', 'text', null, null, null, $mt, 0);

        $result = $this->strategy->execute($mt, new SyncConfirmation());

        $this->assertSame(1, $result->itemsUpdated);
        $this->assertSame(1, $result->additions['customFieldValues']);

        // Verify version incremented
        $this->getEntityManager()->refresh($product);
        $this->assertSame(2, $product->getVersion());
    }

    public function testExecuteIsIdempotent(): void
    {
        $mt      = $this->createModelType('Product Cat', 'PC-001', ModelCategory::PRODUCT);
        $product = $this->createProduct('P1', 'P1-REF', $mt);
        $cf      = $this->createCustomField('Weight', 'text', null, null, null, $mt, 0);

        // First execute
        $result1 = $this->strategy->execute($mt, new SyncConfirmation());
        $this->assertSame(1, $result1->additions['customFieldValues']);

        // Second execute — no-op
        $result2 = $this->strategy->execute($mt, new SyncConfirmation());
        $this->assertSame(0, $result2->itemsUpdated);
    }
}
