<?php
namespace Tests\Unit\Domain\Product;

use PHPUnit\Framework\TestCase;
use Domain\Product\ProductRepository;

/**
 * Phase 18 — testy generatora linku do feedu Google.
 *
 * ProductRepository::appendCombinationToXml buduje <link> dla pozycji
 * feedu Google. permutation_hash w bazie ma format "attr-val|attr-val".
 * W URL feedu separator między parami to "_" (nie "/"), żeby URL był
 * jednym segmentem dopasowywalnym przez routing pp_routes.
 *
 * Test wywołuje prywatną metodę przez ReflectionMethod z minimalnymi
 * danymi produktu i sprawdza zawartość wynikowego DOMDocument.
 */
class ProductFeedLinkTest extends TestCase
{
    private function buildRepoWithMocks(): ProductRepository
    {
        $mockDb = $this->createMock(\medoo::class);
        $mockDb->method('select')->willReturn([]);
        $mockDb->method('get')->willReturn(null);

        $repo = new ProductRepository($mockDb);

        // appendShippingToXml wywołuje $this->transportRepoForXml->lowestTransportPrice().
        // Inicjalizacja w generateGoogleXmlFeed(); dla unit testu wstrzykujemy mock dynamicznie.
        $transportMock = $this->getMockBuilder(\Domain\Transport\TransportRepository::class)
            ->disableOriginalConstructor()
            ->getMock();
        $transportMock->method('lowestTransportPrice')->willReturn(0.0);
        $repo->transportRepoForXml = $transportMock;

        return $repo;
    }

    private function invokeAppendCombination(ProductRepository $repo, array $product, array $combination): string
    {
        $doc = new \DOMDocument('1.0', 'UTF-8');
        $channelNode = $doc->appendChild($doc->createElement('channel'));

        $method = new \ReflectionMethod(ProductRepository::class, 'appendCombinationToXml');
        $method->setAccessible(true);
        $method->invoke($repo, $doc, $channelNode, $product, $combination, 'https', 'shop.example.com');

        return $doc->saveXML();
    }

    private function baseProduct(array $overrides = []): array
    {
        return array_merge([
            'id'                  => 123,
            'ean'                 => '5901234567890',
            'language'            => [
                'name'              => 'Produkt testowy',
                'xml_name'          => '',
                'short_description' => 'Opis',
                'meta_title'        => '',
                'seo_link'          => 'sukienka-czerwona',
            ],
            'price_brutto'        => 100,
            'price_brutto_promo'  => 0,
            'quantity'            => 10,
            'stock_0_buy'         => 0,
            'wp'                  => 1,
            'images'              => [],
        ], $overrides);
    }

    public function testCombinationLinkUsesUnderscoreInSeoLinkBranch()
    {
        $repo = $this->buildRepoWithMocks();
        $product = $this->baseProduct();
        $combination = [
            'id'                 => 555,
            'permutation_hash'   => '20-170|21-175',
            'price_brutto'       => 120,
            'price_brutto_promo' => 0,
            'quantity'           => 5,
            'stock_0_buy'        => 0,
        ];

        $xml = $this->invokeAppendCombination($repo, $product, $combination);

        $this->assertStringContainsString(
            '<link>https://shop.example.com/sukienka-czerwona/20-170_21-175</link>',
            $xml,
            'Link feedu z seo_link musi używać "_" jako separatora par attr-val'
        );
        $this->assertStringNotContainsString(
            '20-170/21-175',
            $xml,
            'Link feedu nie może zawierać starego separatora "/" między parami atrybutów'
        );
    }

    public function testCombinationLinkUsesUnderscoreInFallbackBranch()
    {
        $repo = $this->buildRepoWithMocks();
        $product = $this->baseProduct([
            'language' => [
                'name'              => 'Sukienka czerwona',
                'xml_name'          => '',
                'short_description' => 'Opis',
                'meta_title'        => '',
                'seo_link'          => '',
            ],
        ]);
        $combination = [
            'id'                 => 555,
            'permutation_hash'   => '20-170|21-175',
            'price_brutto'       => 120,
            'price_brutto_promo' => 0,
            'quantity'           => 5,
            'stock_0_buy'        => 0,
        ];

        $xml = $this->invokeAppendCombination($repo, $product, $combination);

        // Fallback uses "p-{id}-{seo(name)}/...". Helpers::seo stub returns input unchanged.
        $this->assertStringContainsString(
            '<link>https://shop.example.com/p-123-Sukienka czerwona/20-170_21-175</link>',
            $xml,
            'Link fallback (bez seo_link) musi używać "_" jako separatora par attr-val'
        );
    }

    public function testCombinationLinkWithSinglePair()
    {
        $repo = $this->buildRepoWithMocks();
        $product = $this->baseProduct();
        $combination = [
            'id'                 => 555,
            'permutation_hash'   => '20-170',
            'price_brutto'       => 120,
            'price_brutto_promo' => 0,
            'quantity'           => 5,
            'stock_0_buy'        => 0,
        ];

        $xml = $this->invokeAppendCombination($repo, $product, $combination);

        $this->assertStringContainsString(
            '<link>https://shop.example.com/sukienka-czerwona/20-170</link>',
            $xml,
            'Pojedyncza para attr-val pozostaje bez zmian (str_replace nie ma co podmieniać)'
        );
    }
}
