<?php

namespace DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\PriceCompare\ProductFields\Ceneo;

use DOMElement;
use DOMDocument;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\PriceCompare\ProductFields\CustomProductField;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\ProductField;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\ProductFieldValue;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\ProductFieldXml;
use DOMXPath;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\Value\GpsrProductFieldValue;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Integration\GpsrIntegration;
class GpsrProductField extends CustomProductField implements ProductField, ProductFieldXml
{
    public const FIELD_RESPONSIBLE_PRODUCERS = 'responsibleProducers';
    public const FIELD_RESPONSIBLE_PERSONS = 'responsiblePersons';
    public const FIELD_RESPONSIBLE_ITEM_TAG = 'p';
    public const FIELD_RESPONSIBLE_ITEM_ID_ATTR = 'id';
    public const FIELD_RESPONSIBLE_ITEM_NAME_TAG = 'name';
    public const FIELD_RESPONSIBLE_ITEM_ADDRESS_TAG = 'address';
    public const FIELD_RESPONSIBLE_ITEM_COUNTRY_TAG = 'countryCode';
    public const FIELD_RESPONSIBLE_ITEM_STREET_TAG = 'street';
    public const FIELD_RESPONSIBLE_ITEM_POSTAL_TAG = 'postalCode';
    public const FIELD_RESPONSIBLE_ITEM_CITY_TAG = 'city';
    public const FIELD_RESPONSIBLE_ITEM_CONTACT_TAG = 'contact';
    public const FIELD_RESPONSIBLE_ITEM_EMAIL_TAG = 'email';
    public const FIELD_RESPONSIBLE_ITEM_PHONE_TAG = 'phoneNumber';
    public const SINGLE_ATTR_TAG = 'a';
    public const SINGLE_ATTR_TAG_NAME = 'name';
    public const FIELD_ATTR_TAG_NAME = 'attrs';
    public const VALUE_ATTR_RESPONSIBLE_PRODUCER = 'Producent odpowiedzialny';
    public const VALUE_ATTR_RESPONSIBLE_PERSON = 'Podmiot odpowiedzialny';
    public const VALUE_ATTR_RESPONSIBLE_SAFETY = 'Informacje o bezpieczeństwie';
    private string $field_name;
    private ProductFieldValue $product_value;
    public function __construct(ProductFieldValue $product_value)
    {
        $this->product_value = $product_value;
    }
    public static function get_default_class_value(): string
    {
        return GpsrProductFieldValue::class;
    }
    public static function is_allowed_to_change(): bool
    {
        return \false;
    }
    public static function get_default_field_name(): string
    {
        return 'gpsr_integration';
    }
    public static function get_default_field_nice_name(): string
    {
        return esc_html__('GPSR integration', 'dropshipping-export-free');
    }
    public function get_field_name(): string
    {
        $default = self::get_default_field_name();
        return !empty($this->field_name) ? $this->field_name : $default;
    }
    public function set_field_name(string $string)
    {
        $this->field_name = trim($string);
    }
    public function map_xml_value(DOMElement $element): DOMElement
    {
        $values = $this->get_values_as_array($this->product_value);
        if (\is_array($values)) {
            $producer = $values[GpsrProductFieldValue::KEY_PRODUCER] ?? [];
            $person = $values[GpsrProductFieldValue::KEY_IMPORTER] ?? [];
            $safety = $values[GpsrProductFieldValue::KEY_SAFETY] ?? [];
            $result = $this->add_responsible($element, self::FIELD_RESPONSIBLE_PRODUCERS, $producer);
            if (null !== $result) {
                $this->add_responsible($element, self::FIELD_RESPONSIBLE_PERSONS, $person);
            }
            if (!empty($safety[GpsrIntegration::FIELD_INSTRUCTIONS_DATA])) {
                $this->create_attribute_node($element, self::VALUE_ATTR_RESPONSIBLE_SAFETY, $safety[GpsrIntegration::FIELD_INSTRUCTIONS_DATA] ?? '');
            }
        }
        return $element;
    }
    private function add_responsible(DOMElement $element, string $type, array $responsible_data): ?DOMElement
    {
        if (empty($responsible_data[GpsrIntegration::FIELD_NAME])) {
            return null;
        }
        $id = $responsible_data[GpsrIntegration::FIELD_NAME];
        $root = $element->ownerDocument;
        $offers_node = $root->getElementsByTagName('offers')->item(0);
        if (!$offers_node) {
            return null;
        }
        $responsible_list_node = $this->get_or_create_responsible_node($offers_node, $type);
        $this->create_responsible_node_item_if_not_exists($responsible_list_node, $id, $type, $responsible_data);
        $attribute_name = self::FIELD_RESPONSIBLE_PRODUCERS === $type ? self::VALUE_ATTR_RESPONSIBLE_PRODUCER : self::VALUE_ATTR_RESPONSIBLE_PERSON;
        $this->create_attribute_node($element, $attribute_name, $id);
        return $element;
    }
    private function get_or_create_responsible_node(DOMElement $offers_node, string $type): DOMElement
    {
        $root = $offers_node->ownerDocument;
        $responsible_list_node = $offers_node->getElementsByTagName($type)->item(0);
        if (!$responsible_list_node) {
            $responsible_list_node = $offers_node->appendChild($root->createElement($type));
        }
        return $responsible_list_node;
    }
    private function create_responsible_node_item_if_not_exists(DOMElement $responsible_list_node, string $id, string $type, array $responsible_data): DOMElement
    {
        $root = $responsible_list_node->ownerDocument;
        $xpath = new DOMXPath($root);
        if (null === $this->find_responsible_node_item($xpath, $id, $type)) {
            $new_resposible_item_node = $this->create_responsible_entity_node($root, $responsible_data);
            $responsible_list_node->appendChild($new_resposible_item_node);
        }
        return $responsible_list_node;
    }
    private function create_responsible_entity_node(DOMDocument $root, array $responsible_data): DOMElement
    {
        $p = $root->createElement(self::FIELD_RESPONSIBLE_ITEM_TAG);
        $p->setAttribute(self::FIELD_RESPONSIBLE_ITEM_ID_ATTR, $responsible_data[GpsrIntegration::FIELD_NAME]);
        $p->appendChild($root->createElement(self::FIELD_RESPONSIBLE_ITEM_NAME_TAG, $responsible_data[GpsrIntegration::FIELD_NAME]));
        $address = $root->createElement(self::FIELD_RESPONSIBLE_ITEM_ADDRESS_TAG);
        $address->appendChild($root->createElement(self::FIELD_RESPONSIBLE_ITEM_COUNTRY_TAG, $responsible_data[GpsrIntegration::FIELD_COUNTRY]));
        $address->appendChild($root->createElement(self::FIELD_RESPONSIBLE_ITEM_STREET_TAG, $responsible_data[GpsrIntegration::FIELD_ADDRESS]));
        $address->appendChild($root->createElement(self::FIELD_RESPONSIBLE_ITEM_POSTAL_TAG, $responsible_data[GpsrIntegration::FIELD_POSTCODE]));
        $address->appendChild($root->createElement(self::FIELD_RESPONSIBLE_ITEM_CITY_TAG, $responsible_data[GpsrIntegration::FIELD_CITY]));
        $p->appendChild($address);
        $contact = $root->createElement(self::FIELD_RESPONSIBLE_ITEM_CONTACT_TAG);
        $contact->appendChild($root->createElement(self::FIELD_RESPONSIBLE_ITEM_EMAIL_TAG, $responsible_data[GpsrIntegration::FIELD_EMAIL]));
        $contact->appendChild($root->createElement(self::FIELD_RESPONSIBLE_ITEM_PHONE_TAG, $responsible_data[GpsrIntegration::FIELD_PHONE]));
        $p->appendChild($contact);
        return $p;
    }
    private function find_responsible_node_item(DOMXPath $xpath, string $id, string $list_tag_name): ?DOMElement
    {
        $query = sprintf("/offers/%s/p[@id='%s']", $list_tag_name, $id);
        $result = $xpath->query($query);
        return $result->item(0);
    }
    private function create_attribute_node(DOMElement $element, string $name, string $value): DOMElement
    {
        $root = $element->ownerDocument;
        $attributes_node = $element->getElementsByTagName(self::FIELD_ATTR_TAG_NAME)->item(0);
        if (!$attributes_node) {
            $attributes_node = $element->appendChild($root->createElement(self::FIELD_ATTR_TAG_NAME));
        }
        $a = $root->createElement(self::SINGLE_ATTR_TAG);
        $a->setAttribute(self::SINGLE_ATTR_TAG_NAME, $name);
        $cdata = $root->createCDATASection($value);
        $a->appendChild($cdata);
        $attributes_node->appendChild($a);
        return $attributes_node;
    }
}
