<?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\Shop\Model;

use CpCreation\VitiCore\Behavior\HasImage;
use CpCreation\VitiCore\Behavior\HasTimestamp;
use CpCreation\VitiCore\Behavior\HasTranslatable;
use CpCreation\VitiCore\Behavior\Impl\Image;
use CpCreation\VitiCore\Behavior\Impl\Timestamp;
use CpCreation\VitiCore\Behavior\Impl\Translatable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;

#[ORM\Table(name: 'shop_shop_config')]
#[ORM\HasLifecycleCallbacks]
#[ORM\Entity(repositoryClass: 'CpCreation\VitiCore\Shop\Repository\ShopConfigRepository')]
class ShopConfig implements HasImage, HasTimestamp, HasTranslatable
{
    use Image;
    use Timestamp;
    use Translatable;

    public const string INVOICE_PAYMENT_TERM_IMMEDIATE = 'immediate';
    public const string INVOICE_PAYMENT_TERM_RECEIPT = 'receipt';
    public const string INVOICE_PAYMENT_TERM_15_DAYS = '15_days';
    public const string INVOICE_PAYMENT_TERM_30_DAYS = '30_days';
    public const string INVOICE_PAYMENT_TERM_30_DAYS_END_OF_MONTH = '30_days_end_of_month';
    public const string INVOICE_PAYMENT_TERM_45_DAYS_END_OF_MONTH = '45_days_end_of_month';
    public const string INVOICE_PAYMENT_TERM_60_DAYS = '60_days';

    #[Assert\Valid]
    #[ORM\OneToMany(
        targetEntity: Translation\ShopConfigTranslation::class,
        mappedBy: 'translatable',
        cascade: ['all'],
        indexBy: 'locale',
        orphanRemoval: true
    )]
    protected $translations;

    #[ORM\Id]
    #[ORM\Column(type: 'uuid')]
    #[ORM\GeneratedValue(strategy: 'NONE')]
    private UuidInterface $id;

    #[ORM\Column(type: 'boolean')]
    private bool $hidePriceDefault;

    #[ORM\Column(type: 'boolean')]
    private bool $enableAwardShop;

    #[ORM\OneToMany(
        targetEntity: ShopConfigDisableCountry::class,
        cascade: ['all'],
        mappedBy: 'config',
        orphanRemoval: true
    )]
    #[ORM\OrderBy(['country' => 'ASC'])]
    #[Assert\Valid]
    private Collection $disableCountries;

    #[ORM\Column(type: 'json', nullable: true, options: ['default' => '[]'])]
    private ?array $enableCountriesForShop;

    #[ORM\Column(type: 'datetime', nullable: true)]
    private ?\DateTime $vacationOf = null;

    #[ORM\Column(type: 'datetime', nullable: true)]
    private ?\DateTime $vacationAt = null;

    #[ORM\Column(type: 'boolean')]
    private bool $disableShopForVacation;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $disableOrdersForVacation;

    #[ORM\OneToMany(
        targetEntity: ShopConfigMultiple::class,
        cascade: ['all'],
        mappedBy: 'config',
        orphanRemoval: true
    )]
    #[ORM\OrderBy(['qtyOf' => 'ASC'])]
    #[Assert\Valid]
    private Collection $multiples;

    #[ORM\Column(type: 'boolean')]
    private bool $degrissivityByItem;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $invoice;

    #[ORM\Column(type: 'string', length: 64, nullable: true)]
    private ?string $invoicePaymentTerm = null;

    #[ORM\Column(type: 'string', length: 64, nullable: true)]
    private ?string $invoiceSuffix = null;

    #[ORM\Column(type: 'boolean', options: ['default' => true])]
    private bool $enablePartnerCodeFront;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enableProductPageFront;

    #[ORM\Column(type: 'boolean', options: ['default' => true])]
    private bool $showCategoryMenuFront;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $showPartnerCodeWhenShopBlocked;

    #[ORM\Column(type: 'string', length: 64, nullable: true)]
    private ?string $googleTagManagerId = null;

    #[ORM\Column(type: 'json', nullable: true, options: ['default' => '[]'])]
    private ?array $googleAnalyticsIds = [];

    #[ORM\Column(type: 'json', nullable: true, options: ['default' => '[]'])]
    private ?array $googleAdsConversionLabels = [];

    #[ORM\Column(type: 'json', nullable: true, options: ['default' => '[]'])]
    private ?array $facebookPixelIds = [];

    #[ORM\Column(type: 'json', nullable: true, options: ['default' => '[]'])]
    private ?array $metaConversionsPixelConfigs = [];

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $metaConversionsAccessToken = null;

    #[ORM\Column(type: 'string', length: 128, nullable: true)]
    private ?string $metaTestEventCode = null;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enableMetaBrowserEventTracking = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enableMetaConversionsApiTracking = false;

    #[Assert\Url]
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private ?string $matomoUrl = null;

    #[Assert\Url]
    #[ORM\Column(type: 'string', length: 255, nullable: true)]
    private ?string $matomoServerUrl = null;

    #[Assert\Positive]
    #[ORM\Column(type: 'integer', nullable: true)]
    private ?int $matomoSiteId = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $trackingHeadScripts = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $trackingBodyScripts = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $trackingCheckoutScripts = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $trackingPaymentConfirmationScripts = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $trackingPaymentErrorScripts = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $trackingPaymentCanceledScripts = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $trackingContactScripts = null;

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $trackingContactSuccessScripts = null;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enableCheckoutEventTracking = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enablePaymentSuccessEventTracking = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enablePaymentErrorEventTracking = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enablePaymentCanceledEventTracking = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enableContactPageEventTracking = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enableContactSuccessEventTracking = false;

    #[ORM\Column(type: 'boolean', options: ['default' => false])]
    private bool $enableMatomoEcommerceTracking = false;

    public function __construct()
    {
        $this->id = Uuid::uuid4();
        $this->hidePriceDefault = false;
        $this->enableAwardShop = false;
        $this->disableCountries = new ArrayCollection();
        $this->enableCountriesForShop = [];
        $this->disableShopForVacation = false;
        $this->disableOrdersForVacation = false;
        $this->multiples = new ArrayCollection();
        $this->degrissivityByItem = false;
        $this->invoice = false;
        $this->enablePartnerCodeFront = true;
        $this->enableProductPageFront = false;
        $this->showCategoryMenuFront = true;
        $this->showPartnerCodeWhenShopBlocked = false;
    }

    public function getId(): UuidInterface
    {
        return $this->id;
    }

    public function isHidePriceDefault(): bool
    {
        return $this->hidePriceDefault;
    }

    public function setHidePriceDefault(bool $hidePriceDefault): void
    {
        $this->hidePriceDefault = $hidePriceDefault;
    }

    public function shouldShowPrices(?string $partnerCode): bool
    {
        return !$this->hidePriceDefault
            || (null !== $partnerCode && '' !== mb_trim($partnerCode));
    }

    public function isEnableAwardShop(): bool
    {
        return $this->enableAwardShop;
    }

    public function setEnableAwardShop(bool $enableAwardShop): void
    {
        $this->enableAwardShop = $enableAwardShop;
    }

    public function addDisableCountry(ShopConfigDisableCountry $disableCountry): void
    {
        if ($this->disableCountries->contains($disableCountry)) {
            return;
        }

        $disableCountry->setConfig($this);
        $this->disableCountries->add($disableCountry);
    }

    public function removeDisableCountry(ShopConfigDisableCountry $disableCountry): void
    {
        if (!$this->disableCountries->contains($disableCountry)) {
            return;
        }

        $this->disableCountries->removeElement($disableCountry);
    }

    public function getDisableCountries(): Collection
    {
        return $this->disableCountries;
    }

    public function getEnableCountriesForShop(): ?array
    {
        return $this->enableCountriesForShop;
    }

    public function setEnableCountriesForShop(?array $enableCountriesForShop): void
    {
        $this->enableCountriesForShop = $enableCountriesForShop;
    }

    public function addMultiple(ShopConfigMultiple $multiple): void
    {
        if ($this->multiples->contains($multiple)) {
            return;
        }

        $multiple->setConfig($this);
        $this->multiples->add($multiple);
    }

    public function removeMultiple(ShopConfigMultiple $multiple): void
    {
        if (!$this->multiples->contains($multiple)) {
            return;
        }

        $multiple->setConfig(null);
        $this->multiples->removeElement($multiple);
    }

    public function getVacationOf(): ?\DateTime
    {
        return $this->vacationOf;
    }

    public function setVacationOf(?\DateTime $vacationOf): void
    {
        $this->vacationOf = $vacationOf;
    }

    public function getVacationAt(): ?\DateTime
    {
        return $this->vacationAt;
    }

    public function setVacationAt(?\DateTime $vacationAt): void
    {
        $this->vacationAt = $vacationAt;
    }

    public function isVacationActive(?\DateTimeInterface $referenceDate = null): bool
    {
        if (null === $this->vacationOf || null === $this->vacationAt) {
            return false;
        }

        $referenceDate ??= new \DateTimeImmutable('now');

        return $this->vacationOf < $referenceDate && $this->vacationAt > $referenceDate;
    }

    public function isShopDisabledForVacation(?\DateTimeInterface $referenceDate = null): bool
    {
        return $this->disableShopForVacation && $this->isVacationActive($referenceDate);
    }

    public function isDisableShopForVacation(): bool
    {
        return $this->disableShopForVacation;
    }

    public function setDisableShopForVacation(bool $disableShopForVacation): void
    {
        $this->disableShopForVacation = $disableShopForVacation;
    }

    public function isOrderingDisabledForVacation(?\DateTimeInterface $referenceDate = null): bool
    {
        return $this->disableOrdersForVacation && $this->isVacationActive($referenceDate);
    }

    public function isDisableOrdersForVacation(): bool
    {
        return $this->disableOrdersForVacation;
    }

    public function setDisableOrdersForVacation(bool $disableOrdersForVacation): void
    {
        $this->disableOrdersForVacation = $disableOrdersForVacation;
    }

    public function getMultiples(): Collection
    {
        return $this->multiples;
    }

    public function isDegrissivityByItem(): bool
    {
        return $this->degrissivityByItem;
    }

    public function setDegrissivityByItem(bool $degrissivityByItem): void
    {
        $this->degrissivityByItem = $degrissivityByItem;
    }

    public function isInvoice(): bool
    {
        return $this->invoice;
    }

    public function setInvoice(bool $invoice): void
    {
        $this->invoice = $invoice;
    }

    public function getInvoicePaymentTerm(): ?string
    {
        return $this->invoicePaymentTerm;
    }

    public function setInvoicePaymentTerm(?string $invoicePaymentTerm): void
    {
        $allowed = array_values(self::getInvoicePaymentTermChoices());

        if (null !== $invoicePaymentTerm && !\in_array($invoicePaymentTerm, $allowed, true)) {
            $invoicePaymentTerm = null;
        }

        $this->invoicePaymentTerm = $invoicePaymentTerm;
    }

    public function getInvoiceSuffix(): ?string
    {
        return $this->normalizeInvoicePrefix($this->invoiceSuffix);
    }

    public function getInvoicePrefix(): ?string
    {
        return $this->getInvoiceSuffix();
    }

    public function setInvoiceSuffix(?string $invoiceSuffix): void
    {
        $this->invoiceSuffix = $this->normalizeInvoicePrefix($invoiceSuffix);
    }

    public function formatInvoiceReference(int $year, int $number, bool $credit = false): string
    {
        $parts = [];
        $prefix = $this->getInvoicePrefix();

        if (null !== $prefix) {
            $parts[] = $prefix;
        }

        if ($credit) {
            $parts[] = 'Avoir';
        }

        $parts[] = (string) $year;
        $parts[] = \sprintf('%05d', $number);

        return implode('-', $parts);
    }

    /**
     * @return array<string, string>
     */
    public static function getInvoicePaymentTermChoices(): array
    {
        return [
            'Comptant' => self::INVOICE_PAYMENT_TERM_IMMEDIATE,
            'A réception' => self::INVOICE_PAYMENT_TERM_RECEIPT,
            'Sous 15 jours' => self::INVOICE_PAYMENT_TERM_15_DAYS,
            'Sous 30 jours' => self::INVOICE_PAYMENT_TERM_30_DAYS,
            '30 jours fin de mois' => self::INVOICE_PAYMENT_TERM_30_DAYS_END_OF_MONTH,
            '45 jours fin de mois' => self::INVOICE_PAYMENT_TERM_45_DAYS_END_OF_MONTH,
            '60 jours nets' => self::INVOICE_PAYMENT_TERM_60_DAYS,
        ];
    }

    #[Assert\Callback]
    public function validateInvoiceConfiguration(ExecutionContextInterface $context): void
    {
        if ($this->invoice && (null === $this->invoicePaymentTerm || '' === $this->invoicePaymentTerm)) {
            $context
                ->buildViolation('Veuillez sélectionner des conditions de règlement lorsque la facturation est activée.')
                ->atPath('invoicePaymentTerm')
                ->addViolation();
        }
    }

    public function isEnablePartnerCodeFront(): bool
    {
        return $this->enablePartnerCodeFront;
    }

    public function setEnablePartnerCodeFront(bool $enablePartnerCodeFront): void
    {
        $this->enablePartnerCodeFront = $enablePartnerCodeFront;
    }

    public function isEnableProductPageFront(): bool
    {
        return $this->enableProductPageFront;
    }

    public function setEnableProductPageFront(bool $enableProductPageFront): void
    {
        $this->enableProductPageFront = $enableProductPageFront;
    }

    public function isShowCategoryMenuFront(): bool
    {
        return $this->showCategoryMenuFront;
    }

    public function setShowCategoryMenuFront(bool $showCategoryMenuFront): void
    {
        $this->showCategoryMenuFront = $showCategoryMenuFront;
    }

    public function isShowPartnerCodeWhenShopBlocked(): bool
    {
        return $this->showPartnerCodeWhenShopBlocked;
    }

    public function setShowPartnerCodeWhenShopBlocked(bool $showPartnerCodeWhenShopBlocked): void
    {
        $this->showPartnerCodeWhenShopBlocked = $showPartnerCodeWhenShopBlocked;
    }

    public function getGoogleTagManagerId(): ?string
    {
        return $this->googleTagManagerId;
    }

    public function setGoogleTagManagerId(?string $googleTagManagerId): void
    {
        $googleTagManagerId = null !== $googleTagManagerId ? mb_strtoupper(mb_trim($googleTagManagerId)) : null;
        $this->googleTagManagerId = '' !== (string) $googleTagManagerId ? $googleTagManagerId : null;
    }

    /**
     * @return list<string>
     */
    public function getGoogleAnalyticsIds(): array
    {
        return $this->normalizeTrackerIds($this->googleAnalyticsIds);
    }

    /**
     * @param array<int|string, string>|null $googleAnalyticsIds
     */
    public function setGoogleAnalyticsIds(?array $googleAnalyticsIds): void
    {
        $this->googleAnalyticsIds = $this->normalizeTrackerIds($googleAnalyticsIds);
    }

    /**
     * @return array<string, string>
     */
    public function getGoogleAdsConversionLabels(): array
    {
        return $this->normalizeGoogleAdsConversionLabels($this->googleAdsConversionLabels);
    }

    /**
     * @param array<int|string, mixed>|null $googleAdsConversionLabels
     */
    public function setGoogleAdsConversionLabels(?array $googleAdsConversionLabels): void
    {
        $this->googleAdsConversionLabels = $this->normalizeGoogleAdsConversionLabels($googleAdsConversionLabels);
    }

    public function getGoogleAdsConversionSendTo(string $eventName): ?string
    {
        $labels = $this->getGoogleAdsConversionLabels();

        return $labels[$eventName] ?? null;
    }

    /**
     * @return list<string>
     */
    public function getFacebookPixelIds(): array
    {
        return $this->normalizeTrackerIds($this->facebookPixelIds);
    }

    /**
     * @param array<int|string, string>|null $facebookPixelIds
     */
    public function setFacebookPixelIds(?array $facebookPixelIds): void
    {
        $this->facebookPixelIds = $this->normalizeTrackerIds($facebookPixelIds);
    }

    /**
     * @return list<array{pixelId: string, accessToken: string}>
     */
    public function getMetaConversionsPixelConfigs(): array
    {
        $configs = $this->normalizeMetaConversionsPixelConfigs($this->metaConversionsPixelConfigs);

        if (null !== $this->metaConversionsPixelConfigs) {
            return $configs;
        }

        $accessToken = $this->getMetaConversionsAccessToken();
        $pixelId = $this->getFacebookPixelIds()[0] ?? null;

        if (null === $accessToken || null === $pixelId) {
            return [];
        }

        return [[
            'pixelId' => $pixelId,
            'accessToken' => $accessToken,
        ]];
    }

    /**
     * @param array<int|string, mixed>|null $metaConversionsPixelConfigs
     */
    public function setMetaConversionsPixelConfigs(?array $metaConversionsPixelConfigs): void
    {
        $this->metaConversionsPixelConfigs = $this->normalizeMetaConversionsPixelConfigs($metaConversionsPixelConfigs);
    }

    public function getMetaConversionsAccessToken(): ?string
    {
        return $this->metaConversionsAccessToken;
    }

    public function setMetaConversionsAccessToken(?string $metaConversionsAccessToken): void
    {
        $metaConversionsAccessToken = null !== $metaConversionsAccessToken
            ? mb_trim($metaConversionsAccessToken)
            : null;
        $this->metaConversionsAccessToken = '' !== (string) $metaConversionsAccessToken
            ? $metaConversionsAccessToken
            : null;
    }

    public function getMetaTestEventCode(): ?string
    {
        return $this->metaTestEventCode;
    }

    public function setMetaTestEventCode(?string $metaTestEventCode): void
    {
        $metaTestEventCode = null !== $metaTestEventCode ? mb_trim($metaTestEventCode) : null;
        $this->metaTestEventCode = '' !== (string) $metaTestEventCode
            ? mb_substr($metaTestEventCode, 0, 128)
            : null;
    }

    public function isEnableMetaBrowserEventTracking(): bool
    {
        return $this->enableMetaBrowserEventTracking;
    }

    public function setEnableMetaBrowserEventTracking(bool $enableMetaBrowserEventTracking): void
    {
        $this->enableMetaBrowserEventTracking = $enableMetaBrowserEventTracking;
    }

    public function isEnableMetaConversionsApiTracking(): bool
    {
        return $this->enableMetaConversionsApiTracking;
    }

    public function setEnableMetaConversionsApiTracking(bool $enableMetaConversionsApiTracking): void
    {
        $this->enableMetaConversionsApiTracking = $enableMetaConversionsApiTracking;
    }

    public function isMetaConversionsApiConfigured(): bool
    {
        return [] !== $this->getMetaConversionsPixelConfigs()
            && $this->enableMetaConversionsApiTracking;
    }

    public function getMatomoUrl(): ?string
    {
        return $this->matomoUrl;
    }

    public function setMatomoUrl(?string $matomoUrl): void
    {
        $this->matomoUrl = $this->normalizeMatomoUrl($matomoUrl);
    }

    public function getMatomoServerUrl(): ?string
    {
        return $this->matomoServerUrl;
    }

    public function setMatomoServerUrl(?string $matomoServerUrl): void
    {
        $this->matomoServerUrl = $this->normalizeMatomoUrl($matomoServerUrl);
    }

    public function getMatomoTrackingServerUrl(): ?string
    {
        return $this->matomoServerUrl ?? $this->matomoUrl;
    }

    public function getMatomoSiteId(): ?int
    {
        return $this->matomoSiteId;
    }

    public function setMatomoSiteId(?int $matomoSiteId): void
    {
        $this->matomoSiteId = null !== $matomoSiteId && $matomoSiteId > 0 ? $matomoSiteId : null;
    }

    public function isMatomoConfigured(): bool
    {
        return null !== $this->matomoUrl && null !== $this->matomoSiteId;
    }

    public function getTrackingHeadScripts(): ?string
    {
        return $this->trackingHeadScripts;
    }

    public function setTrackingHeadScripts(?string $trackingHeadScripts): void
    {
        $trackingHeadScripts = null !== $trackingHeadScripts ? mb_trim($trackingHeadScripts) : null;
        $this->trackingHeadScripts = '' !== (string) $trackingHeadScripts ? $trackingHeadScripts : null;
    }

    public function getTrackingBodyScripts(): ?string
    {
        return $this->trackingBodyScripts;
    }

    public function setTrackingBodyScripts(?string $trackingBodyScripts): void
    {
        $trackingBodyScripts = null !== $trackingBodyScripts ? mb_trim($trackingBodyScripts) : null;
        $this->trackingBodyScripts = '' !== (string) $trackingBodyScripts ? $trackingBodyScripts : null;
    }

    public function getTrackingCheckoutScripts(): ?string
    {
        return $this->trackingCheckoutScripts;
    }

    public function setTrackingCheckoutScripts(?string $trackingCheckoutScripts): void
    {
        $trackingCheckoutScripts = null !== $trackingCheckoutScripts ? mb_trim($trackingCheckoutScripts) : null;
        $this->trackingCheckoutScripts = '' !== (string) $trackingCheckoutScripts ? $trackingCheckoutScripts : null;
    }

    public function getTrackingPaymentConfirmationScripts(): ?string
    {
        return $this->trackingPaymentConfirmationScripts;
    }

    public function setTrackingPaymentConfirmationScripts(?string $trackingPaymentConfirmationScripts): void
    {
        $trackingPaymentConfirmationScripts = null !== $trackingPaymentConfirmationScripts ? mb_trim($trackingPaymentConfirmationScripts) : null;
        $this->trackingPaymentConfirmationScripts = '' !== (string) $trackingPaymentConfirmationScripts ? $trackingPaymentConfirmationScripts : null;
    }

    public function getTrackingPaymentErrorScripts(): ?string
    {
        return $this->trackingPaymentErrorScripts;
    }

    public function setTrackingPaymentErrorScripts(?string $trackingPaymentErrorScripts): void
    {
        $trackingPaymentErrorScripts = null !== $trackingPaymentErrorScripts ? mb_trim($trackingPaymentErrorScripts) : null;
        $this->trackingPaymentErrorScripts = '' !== (string) $trackingPaymentErrorScripts ? $trackingPaymentErrorScripts : null;
    }

    public function getTrackingPaymentCanceledScripts(): ?string
    {
        return $this->trackingPaymentCanceledScripts;
    }

    public function setTrackingPaymentCanceledScripts(?string $trackingPaymentCanceledScripts): void
    {
        $trackingPaymentCanceledScripts = null !== $trackingPaymentCanceledScripts ? mb_trim($trackingPaymentCanceledScripts) : null;
        $this->trackingPaymentCanceledScripts = '' !== (string) $trackingPaymentCanceledScripts ? $trackingPaymentCanceledScripts : null;
    }

    public function getTrackingContactScripts(): ?string
    {
        return $this->trackingContactScripts;
    }

    public function setTrackingContactScripts(?string $trackingContactScripts): void
    {
        $trackingContactScripts = null !== $trackingContactScripts ? mb_trim($trackingContactScripts) : null;
        $this->trackingContactScripts = '' !== (string) $trackingContactScripts ? $trackingContactScripts : null;
    }

    public function getTrackingContactSuccessScripts(): ?string
    {
        return $this->trackingContactSuccessScripts;
    }

    public function setTrackingContactSuccessScripts(?string $trackingContactSuccessScripts): void
    {
        $trackingContactSuccessScripts = null !== $trackingContactSuccessScripts ? mb_trim($trackingContactSuccessScripts) : null;
        $this->trackingContactSuccessScripts = '' !== (string) $trackingContactSuccessScripts ? $trackingContactSuccessScripts : null;
    }

    public function isEnableCheckoutEventTracking(): bool
    {
        return $this->enableCheckoutEventTracking;
    }

    public function setEnableCheckoutEventTracking(bool $enableCheckoutEventTracking): void
    {
        $this->enableCheckoutEventTracking = $enableCheckoutEventTracking;
    }

    public function isEnablePaymentSuccessEventTracking(): bool
    {
        return $this->enablePaymentSuccessEventTracking;
    }

    public function setEnablePaymentSuccessEventTracking(bool $enablePaymentSuccessEventTracking): void
    {
        $this->enablePaymentSuccessEventTracking = $enablePaymentSuccessEventTracking;
    }

    public function isEnablePaymentErrorEventTracking(): bool
    {
        return $this->enablePaymentErrorEventTracking;
    }

    public function setEnablePaymentErrorEventTracking(bool $enablePaymentErrorEventTracking): void
    {
        $this->enablePaymentErrorEventTracking = $enablePaymentErrorEventTracking;
    }

    public function isEnablePaymentCanceledEventTracking(): bool
    {
        return $this->enablePaymentCanceledEventTracking;
    }

    public function setEnablePaymentCanceledEventTracking(bool $enablePaymentCanceledEventTracking): void
    {
        $this->enablePaymentCanceledEventTracking = $enablePaymentCanceledEventTracking;
    }

    public function isEnableContactPageEventTracking(): bool
    {
        return $this->enableContactPageEventTracking;
    }

    public function setEnableContactPageEventTracking(bool $enableContactPageEventTracking): void
    {
        $this->enableContactPageEventTracking = $enableContactPageEventTracking;
    }

    public function isEnableContactSuccessEventTracking(): bool
    {
        return $this->enableContactSuccessEventTracking;
    }

    public function setEnableContactSuccessEventTracking(bool $enableContactSuccessEventTracking): void
    {
        $this->enableContactSuccessEventTracking = $enableContactSuccessEventTracking;
    }

    public function isEnableMatomoEcommerceTracking(): bool
    {
        return $this->enableMatomoEcommerceTracking;
    }

    public function setEnableMatomoEcommerceTracking(bool $enableMatomoEcommerceTracking): void
    {
        $this->enableMatomoEcommerceTracking = $enableMatomoEcommerceTracking;
    }

    /**
     * @param array<int|string, mixed>|null $ids
     *
     * @return list<string>
     */
    private function normalizeTrackerIds(?array $ids): array
    {
        if (null === $ids) {
            return [];
        }

        $normalized = [];

        foreach ($ids as $id) {
            if (!\is_scalar($id)) {
                continue;
            }

            $value = mb_strtoupper(mb_trim((string) $id));

            if ('' === $value || \in_array($value, $normalized, true)) {
                continue;
            }

            $normalized[] = $value;
        }

        return $normalized;
    }

    /**
     * @param array<int|string, mixed>|null $labels
     *
     * @return array<string, string>
     */
    private function normalizeGoogleAdsConversionLabels(?array $labels): array
    {
        if (null === $labels) {
            return [];
        }

        $normalized = [];

        foreach ($labels as $eventName => $sendTo) {
            if (\is_array($sendTo)) {
                $eventName = $sendTo['event'] ?? $sendTo['eventName'] ?? $sendTo['event_name'] ?? $eventName;
                $sendTo = $sendTo['sendTo'] ?? $sendTo['send_to'] ?? $sendTo['conversion'] ?? null;
            }

            if (!\is_scalar($eventName) || !\is_scalar($sendTo)) {
                continue;
            }

            $eventName = mb_trim((string) $eventName);
            $sendTo = mb_trim((string) $sendTo);

            if ('' === $eventName || '' === $sendTo) {
                continue;
            }

            $normalized[$eventName] = $sendTo;
        }

        return $normalized;
    }

    /**
     * @param array<int|string, mixed>|null $configs
     *
     * @return list<array{pixelId: string, accessToken: string}>
     */
    private function normalizeMetaConversionsPixelConfigs(?array $configs): array
    {
        if (null === $configs) {
            return [];
        }

        $normalized = [];
        $seenPixelIds = [];

        foreach ($configs as $config) {
            if (!\is_array($config)) {
                continue;
            }

            $pixelId = $config['pixelId'] ?? $config['pixel_id'] ?? null;
            $accessToken = $config['accessToken'] ?? $config['access_token'] ?? null;

            if (!\is_scalar($pixelId) || !\is_scalar($accessToken)) {
                continue;
            }

            $pixelId = mb_trim((string) $pixelId);
            $accessToken = mb_trim((string) $accessToken);

            if ('' === $pixelId || '' === $accessToken || \in_array($pixelId, $seenPixelIds, true)) {
                continue;
            }

            $seenPixelIds[] = $pixelId;
            $normalized[] = [
                'pixelId' => $pixelId,
                'accessToken' => $accessToken,
            ];
        }

        return $normalized;
    }

    private function normalizeInvoicePrefix(?string $invoicePrefix): ?string
    {
        $invoicePrefix = null !== $invoicePrefix ? mb_trim($invoicePrefix) : null;

        if (null === $invoicePrefix || '' === $invoicePrefix) {
            return null;
        }

        $invoicePrefix = preg_replace('/[-\\s\\/]+/u', '-', $invoicePrefix) ?? $invoicePrefix;
        $invoicePrefix = mb_trim($invoicePrefix, '-');

        return '' !== $invoicePrefix ? $invoicePrefix : null;
    }

    private function normalizeMatomoUrl(?string $matomoUrl): ?string
    {
        $matomoUrl = null !== $matomoUrl ? mb_trim($matomoUrl) : null;

        if (null === $matomoUrl || '' === $matomoUrl) {
            return null;
        }

        return mb_rtrim($matomoUrl, '/') . '/';
    }
}
