<?php

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Tests\Cart\LegacyOrderImport;

use CpCreation\VitiCore\Cart\LegacyOrderImport\LegacyOrderImporter;
use CpCreation\VitiCore\Cart\LegacyOrderImport\LegacyOrderImportMapping;
use CpCreation\VitiCore\Cart\LegacyOrderImport\LegacyOrderSourceReader;
use CpCreation\VitiCore\Cart\LegacyOrderImport\LegacyPricingSnapshotBuilder;
use Doctrine\DBAL\DriverManager;
use PHPUnit\Framework\TestCase;

final class LegacyOrderImporterUnresolvedMappingTest extends TestCase
{
    public function testAnUnresolvedGeneratedVariantRemainsABlockingPreflightError(): void
    {
        $target = DriverManager::getConnection([
            'driver' => 'pdo_sqlite',
            'memory' => true,
        ]);
        $importer = new LegacyOrderImporter(
            $target,
            new LegacyOrderSourceReader(),
            new LegacyPricingSnapshotBuilder(),
        );
        $sourceVariantId = '11111111-1111-4111-8111-111111111111';
        $mapping = $this->mappingFromJson(<<<JSON
            {
                "variants": {
                    "{$sourceVariantId}": "__A_COMPLETER__"
                }
            }
            JSON);
        $errors = [];
        $warnings = [];
        $resolveVariants = new \ReflectionMethod($importer, 'resolveVariants');

        try {
            $resolved = $resolveVariants->invokeArgs($importer, [[
                'source-cart' => [[
                    'source_variant_id' => $sourceVariantId,
                ]],
            ], $mapping, &$errors, &$warnings]);

            self::assertNull($resolved[$sourceVariantId]);
            self::assertNotEmpty($errors);
            self::assertStringContainsString($sourceVariantId, implode("\n", $errors));
            self::assertStringContainsString('reste a completer', implode("\n", $errors));
        } finally {
            $target->close();
        }
    }

    public function testRemovingAGeneratedVariantEntryRemainsABlockingPreflightError(): void
    {
        $target = DriverManager::getConnection([
            'driver' => 'pdo_sqlite',
            'memory' => true,
        ]);
        $importer = new LegacyOrderImporter(
            $target,
            new LegacyOrderSourceReader(),
            new LegacyPricingSnapshotBuilder(),
        );
        $sourceVariantId = '11111111-1111-4111-8111-111111111111';
        $mapping = $this->versionedMapping([
            'variants' => [],
        ]);
        $errors = [];
        $warnings = [];
        $resolveVariants = new \ReflectionMethod($importer, 'resolveVariants');

        try {
            $resolved = $resolveVariants->invokeArgs($importer, [[
                'source-cart' => [[
                    'source_variant_id' => $sourceVariantId,
                ]],
            ], $mapping, &$errors, &$warnings]);

            self::assertNull($resolved[$sourceVariantId]);
            self::assertStringContainsString('a ete retiree du fichier genere', implode("\n", $errors));
            self::assertStringContainsString($sourceVariantId, implode("\n", $errors));
        } finally {
            $target->close();
        }
    }

    public function testRemovingAGeneratedPaymentMethodEntryIsBlocking(): void
    {
        $target = DriverManager::getConnection([
            'driver' => 'pdo_sqlite',
            'memory' => true,
        ]);
        $importer = new LegacyOrderImporter(
            $target,
            new LegacyOrderSourceReader(),
            new LegacyPricingSnapshotBuilder(),
        );
        $mapping = $this->versionedMapping([
            'payment_methods' => [],
        ]);
        $warnings = [];
        $resolvePaymentMethod = new \ReflectionMethod($importer, 'resolvePaymentMethod');

        try {
            $resolvePaymentMethod->invokeArgs($importer, [[
                'source_payment_method' => 'e-transactions',
            ], $mapping, true, &$warnings]);
            self::fail('La suppression d un moyen de paiement genere aurait du bloquer le preflight.');
        } catch (\RuntimeException $exception) {
            self::assertStringContainsString('moyen de paiement source "e-transactions"', $exception->getMessage());
            self::assertStringContainsString('a ete retiree du fichier genere', $exception->getMessage());
        } finally {
            $target->close();
        }
    }

    public function testRemovingAGeneratedDeliveryMethodEntryIsBlocking(): void
    {
        $target = DriverManager::getConnection([
            'driver' => 'pdo_sqlite',
            'memory' => true,
        ]);
        $importer = new LegacyOrderImporter(
            $target,
            new LegacyOrderSourceReader(),
            new LegacyPricingSnapshotBuilder(),
        );
        $sourceDeliveryMethodId = '22222222-2222-4222-8222-222222222222';
        $mapping = $this->versionedMapping([
            'delivery_methods' => [],
        ]);
        $warnings = [];
        $resolveDeliveryMethod = new \ReflectionMethod($importer, 'resolveDeliveryMethod');

        try {
            $resolveDeliveryMethod->invokeArgs($importer, [[
                'source_delivery_method_id' => $sourceDeliveryMethodId,
            ], $mapping, &$warnings]);
            self::fail('La suppression d un mode de livraison genere aurait du bloquer le preflight.');
        } catch (\RuntimeException $exception) {
            self::assertStringContainsString('mode de livraison source '.$sourceDeliveryMethodId, $exception->getMessage());
            self::assertStringContainsString('a ete retiree du fichier genere', $exception->getMessage());
        } finally {
            $target->close();
        }
    }

    private function mappingFromJson(string $json): LegacyOrderImportMapping
    {
        $path = tempnam(sys_get_temp_dir(), 'viti-unresolved-legacy-map-');
        self::assertNotFalse($path);

        try {
            self::assertNotFalse(file_put_contents($path, $json));

            return LegacyOrderImportMapping::fromFile($path);
        } finally {
            @unlink($path);
        }
    }

    /**
     * @param array<string, mixed> $sections
     */
    private function versionedMapping(array $sections): LegacyOrderImportMapping
    {
        return $this->mappingFromJson(json_encode(array_replace([
            'schema_version' => 1,
            'source' => [
                'source_id' => 'legacy-source',
                'source_key' => 'stable-source-key',
                'scope' => 'all',
            ],
            'variants' => [],
            'payment_methods' => [],
            'delivery_methods' => [],
        ], $sections), \JSON_THROW_ON_ERROR));
    }
}
