<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\User\Import;

use CpCreation\VitiCore\Product\Model\ProductPriceGroup;
use CpCreation\VitiCore\User\Model\ImportedClientGroup;
use CpCreation\VitiCore\User\Repository\ImportedClientGroupRepository;

final readonly class ClientImporter
{
    public function __construct(
        private ImportedClientGroupRepository $importedClientGroupRepository,
    ) {}

    /**
     * @param array<string, ?ProductPriceGroup> $groupMappings Source group names indexed to their VitiCore group, or null when ignored
     */
    public function import(ClientImportAnalysis $analysis, array $groupMappings): ClientImportResult
    {
        $uniqueRows = [];
        $duplicatesInFile = 0;

        foreach ($analysis->rows as $row) {
            if (isset($uniqueRows[$row->email])) {
                ++$duplicatesInFile;

                continue;
            }

            if (!array_key_exists($row->sourceGroup, $groupMappings)) {
                throw new \InvalidArgumentException(sprintf('No target group was mapped for "%s".', $row->sourceGroup));
            }

            $uniqueRows[$row->email] = $row;
        }

        $existingItems = $this->importedClientGroupRepository->findIndexedByEmails(array_keys($uniqueRows));

        $created = 0;
        $updated = 0;
        $unchanged = 0;
        $ignored = 0;
        foreach ($uniqueRows as $email => $row) {
            $targetGroup = $groupMappings[$row->sourceGroup];
            if (!$targetGroup instanceof ProductPriceGroup) {
                ++$ignored;

                continue;
            }

            $existingItem = $existingItems[$email] ?? null;

            if ($existingItem instanceof ImportedClientGroup) {
                if ($existingItem->getGroup()->getId()->equals($targetGroup->getId())) {
                    ++$unchanged;

                    continue;
                }

                $existingItem->setGroup($targetGroup);
                ++$updated;

                continue;
            }

            $this->importedClientGroupRepository->persist(new ImportedClientGroup($email, $targetGroup));
            ++$created;
        }

        if (0 < $created + $updated) {
            $this->importedClientGroupRepository->flush();
        }

        return new ClientImportResult(
            $created,
            $updated,
            $unchanged,
            $ignored,
            $duplicatesInFile,
        );
    }
}
