<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\Order;

use Gls\GlsPoland\AdePlus\ParcelShop\ParcelShop;

final class OrderParcelShopNoteUpdater
{
    private const NOTE_START = '[GLS ParcelShop]';
    private const NOTE_END = '[/GLS ParcelShop]';

    public function syncFromParcelShop(\Order $order, ParcelShop $parcelShop): void
    {
        $this->sync($order, [
            'id' => $parcelShop->getId(),
            'name' => trim(sprintf('%s %s %s', $parcelShop->getName1(), $parcelShop->getName2(), $parcelShop->getName3())),
            'address' => implode(', ', array_filter([
                $parcelShop->getStreet(),
                trim(sprintf('%s %s', $parcelShop->getZipCode(), $parcelShop->getCity())),
            ])),
        ]);
    }

    /**
     * @param array{id?: string, name?: string, address?: string} $parcelShop
     */
    public function sync(\Order $order, array $parcelShop): void
    {
        if (!\Validate::isLoadedObject($order) || empty($parcelShop['id'])) {
            return;
        }

        $block = $this->buildBlock($parcelShop);
        $currentNote = trim((string) ($order->note ?? ''));
        $updatedNote = $this->replaceBlock($currentNote, $block);

        if ($updatedNote === $currentNote) {
            return;
        }

        $order->note = $updatedNote;
        $order->update();
    }

    /**
     * @param array{id?: string, name?: string, address?: string} $parcelShop
     */
    private function buildBlock(array $parcelShop): string
    {
        $lines = [
            self::NOTE_START,
            'ID: ' . (string) ($parcelShop['id'] ?? ''),
        ];

        if (!empty($parcelShop['name'])) {
            $lines[] = 'Name: ' . $parcelShop['name'];
        }

        if (!empty($parcelShop['address'])) {
            $lines[] = 'Address: ' . preg_replace('/<br\s*\/?>/i', ', ', (string) $parcelShop['address']);
        }

        $lines[] = self::NOTE_END;

        return implode("\n", $lines);
    }

    private function replaceBlock(string $currentNote, string $block): string
    {
        $pattern = sprintf('/%s.*?%s\s*/s', preg_quote(self::NOTE_START, '/'), preg_quote(self::NOTE_END, '/'));

        if (preg_match($pattern, $currentNote)) {
            return trim((string) preg_replace($pattern, $block . "\n\n", $currentNote));
        }

        if ('' === $currentNote) {
            return $block;
        }

        return $currentNote . "\n\n" . $block;
    }
}
