<?php
declare(strict_types=1);

namespace Autogedal\Labels\Ui\DataProvider\Label\Form;

use Autogedal\Labels\Model\Attribute\ValueOptionsProvider;
use Autogedal\Labels\Model\ResourceModel\Label\CollectionFactory;
use Magento\Backend\Model\UrlInterface as BackendUrl;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Ui\DataProvider\AbstractDataProvider;

class DataProvider extends AbstractDataProvider
{
    /**
     * @var array|null
     */
    protected $loadedData;

    /**
     * @var StoreManagerInterface
     */
    private $storeManager;

    /**
     * @var ValueOptionsProvider
     */
    private $valueOptionsProvider;

    /**
     * @var BackendUrl
     */
    private $backendUrl;

    public function __construct(
        string $name,
        string $primaryFieldName,
        string $requestFieldName,
        CollectionFactory $collectionFactory,
        StoreManagerInterface $storeManager,
        ValueOptionsProvider $valueOptionsProvider,
        BackendUrl $backendUrl,
        array $meta = [],
        array $data = []
    ) {
        $this->collection = $collectionFactory->create();
        $this->storeManager = $storeManager;
        $this->valueOptionsProvider = $valueOptionsProvider;
        $this->backendUrl = $backendUrl;
        parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data);
    }

    public function getMeta(): array
    {
        $meta = parent::getMeta();
        if (isset($meta['conditions']['children']['attr_value']['arguments']['data']['config'])) {
            $meta['conditions']['children']['attr_value']['arguments']['data']['config']['optionsUrl']
                = $this->backendUrl->getUrl('autogedal_labels/label/attributeOptions');
        }

        return $meta;
    }

    public function getData(): array
    {
        if ($this->loadedData !== null) {
            return $this->loadedData;
        }

        $items = $this->collection->getItems();
        foreach ($items as $model) {
            $data = $model->getData();
            $data = $this->processStoresForMultiselect($data);
            $data = $this->processImageData($data, 'prod_img');
            $data = $this->processShapeData($data, 'prod_img', 'prod_shape');
            $data = $this->processDateTimeRangeForForm($data);
            $data = $this->processCategoryForMultiselect($data);
            $data = $this->processCustomerGroupsForMultiselect($data);
            $data = $this->processAttrValueForForm($data);

            $this->loadedData[$model->getId()] = $data;
        }

        if ($this->loadedData === null || $this->loadedData === []) {
            $this->loadedData = [
                0 => $this->getDefaultData(),
            ];
        }

        return $this->loadedData ?? [];
    }

    private function getDefaultData(): array
    {
        return [
            'label_id' => '',
            'name' => '',
            'is_active' => '0',
            'pos' => '0',
            'is_single' => '0',
            'stores' => ['0'],
            'prod_txt' => '',
            'prod_img' => '',
            'prod_shape' => '',
            'prod_label_color' => '',
            'prod_pos' => '0',
            'prod_style' => 'text-align: center; line-height: 60px;',
            'prod_text_style' => '',
            'prod_image_width' => '',
            'prod_image_height' => '',
            'is_new' => '0',
            'is_sale' => '0',
            'special_price_only' => '0',
            'include_type' => '0',
            'include_sku' => '',
            'category_enabled' => '0',
            'category' => [],
            'attr_code' => '',
            'attr_value' => '',
            'attr_multi' => '0',
            'attr_rule' => '0',
            'product_stock_enabled' => '0',
            'stock_less' => '',
            'stock_more' => '',
            'stock_status' => '0',
            'from_date' => '',
            'from_time' => '',
            'to_date' => '',
            'to_time' => '',
            'date_range_enabled' => '0',
            'from_price' => '',
            'to_price' => '',
            'by_price' => '0',
            'price_range_enabled' => '0',
            'customer_groups' => [],
            'customer_group_enabled' => '0',
            'use_for_parent' => '0',
        ];
    }

    /**
     * Convert store CSV string to array for multiselect.
     *
     * @param array $data
     * @return array
     */
    private function processStoresForMultiselect(array $data): array
    {
        if (!isset($data['stores']) || $data['stores'] === null || $data['stores'] === '') {
            return $data;
        }

        $stores = $data['stores'];
        if (is_string($stores)) {
            $ids = array_map('trim', explode(',', $stores));
            $data['stores'] = array_values(array_filter($ids, static function ($value) {
                return $value !== '';
            }));
        }

        return $data;
    }

    private function processImageData(array $data, string $field): array
    {
        if (!empty($data[$field])) {
            $mediaUrl = $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
            $imagePath = ltrim((string)$data[$field], '/');
            if (strpos($imagePath, 'autogedal_label/') !== 0) {
                $imagePath = 'autogedal_label/' . $imagePath;
            }
            $data[$field] = [
                [
                    'name' => $imagePath,
                    'url' => $mediaUrl . $imagePath,
                    'type' => 'image',
                ],
            ];
        }

        return $data;
    }

    private function processShapeData(array $data, string $imageField, string $shapeField): array
    {
        $data[$shapeField] = '';
        if (empty($data[$imageField]) || !is_array($data[$imageField]) || empty($data[$imageField][0]['name'])) {
            return $data;
        }

        $fileName = (string)$data[$imageField][0]['name'];
        if (strtolower(pathinfo($fileName, PATHINFO_EXTENSION)) !== 'svg') {
            return $data;
        }
        $baseName = pathinfo($fileName, PATHINFO_FILENAME);
        $shapeName = preg_replace('/_[0-9a-fA-F]{3,6}$/', '', $baseName);
        $knownShapes = ['circle', 'rquarter', 'rbquarter', 'lquarter', 'lbquarter', 'list', 'note', 'flag', 'banner', 'tag'];

        if (in_array($shapeName, $knownShapes, true)) {
            $data[$shapeField] = $shapeName . '.svg';
        }

        return $data;
    }

    /**
     * Convert category CSV string to array for multiselect.
     *
     * @param array $data
     * @return array
     */
    private function processCategoryForMultiselect(array $data): array
    {
        if (!isset($data['category']) || $data['category'] === null || $data['category'] === '') {
            return $data;
        }
        $category = $data['category'];
        if (is_string($category)) {
            $ids = array_map('trim', explode(',', $category));
            $data['category'] = array_values(array_filter($ids, static function ($value) {
                return $value !== '';
            }));
        }

        return $data;
    }

    /**
     * Convert customer_groups CSV string to array for multiselect.
     *
     * @param array $data
     * @return array
     */
    private function processCustomerGroupsForMultiselect(array $data): array
    {
        if (!isset($data['customer_groups']) || $data['customer_groups'] === null || $data['customer_groups'] === '') {
            return $data;
        }
        $groups = $data['customer_groups'];
        if (is_string($groups)) {
            $ids = array_map('trim', explode(',', $groups));
            $data['customer_groups'] = array_values(array_filter($ids, static function ($value) {
                return $value !== '';
            }));
        }

        return $data;
    }

    private function processAttrValueForForm(array $data): array
    {
        $attrCode = trim((string)($data['attr_code'] ?? ''));
        if ($attrCode === '') {
            return $data;
        }

        $attributeMeta = $this->valueOptionsProvider->get($attrCode);
        if (($attributeMeta['mode'] ?? 'input') === 'multiselect' && isset($data['attr_value']) && is_string($data['attr_value'])) {
            $values = array_values(array_filter(array_map('trim', explode(',', $data['attr_value']))));
            $data['attr_value'] = $values;
            $data['attr_multi'] = '1';
        } elseif (($attributeMeta['mode'] ?? 'input') === 'select' && isset($data['attr_multi']) && (string)$data['attr_multi'] === '1') {
            // Keep legacy values intact, but do not force the multiselect rule for single-value sources.
        }

        return $data;
    }

    private function processDateTimeRangeForForm(array $data): array
    {
        foreach (['from_date', 'to_date'] as $field) {
            $value = isset($data[$field]) ? trim((string)$data[$field]) : '';
            $timeField = $field === 'from_date' ? 'from_time' : 'to_time';

            if ($value === '') {
                $data[$field] = '';
                $data[$timeField] = '';
                continue;
            }

            $parts = preg_split('/\s+/', $value, 2);
            $data[$field] = $parts[0] ?? '';
            $data[$timeField] = $parts[1] ?? ($field === 'from_date' ? '00:00:00' : '23:59:59');
        }

        return $data;
    }

}
