<?php

namespace PortalPeople\qvc\components;

use backend\models\Globalsettingsbe;
use common\models\Base;
use Yii;
use yii\base\Component;
use yii\helpers\Json;

class QvcImportService extends Component
{
    private const CSV_MAP_CONFIG_PATH = '/../config/csv-maps.php';
    private const GLOBAL_MAPPING_DATA_KEY = 'qvc_csv_mapping_encrypted';
    private const GLOBAL_MAPPING_SETTING_NAME = 'QVC CSV Import Mapping';
    private const GLOBAL_MAPPING_SETTING_TYPE = 'QVC Import';

    public static function cartsbeFields(): array
    {
        return [
            'account_code' => 'Account Code',
            'name' => 'Order Name',
            'email' => 'Email',
            'contact' => 'Contact Name',
            'telephone' => 'Telephone',
            'postcode' => 'Postcode',
            'ordernumber' => 'Order Number (ext ref)',
            'porderref' => 'PO Reference',
            'paymentmethod' => 'Payment Method',
            'message' => 'Notes / Message',
            'delivery_notes' => 'Delivery Notes',
            'shippingmethod' => 'Shipping Method',
            'fulladdresses.shipping' => 'Full Address (Shipping)',
            'fulladdresses.shipping.name' => 'Shipping Name',
            'fulladdresses.shipping.firstname' => 'Shipping First Name',
            'fulladdresses.shipping.lastname' => 'Shipping Last Name',
            'fulladdresses.shipping.companyname' => 'Shipping Company Name',
            'fulladdresses.shipping.company_name' => 'Shipping Company Name (Alt)',
            'fulladdresses.shipping.contact' => 'Shipping Contact',
            'fulladdresses.shipping.email' => 'Shipping Email',
            'fulladdresses.shipping.address1' => 'Shipping Address 1',
            'fulladdresses.shipping.address2' => 'Shipping Address 2',
            'fulladdresses.shipping.address3' => 'Shipping Address 3',
            'fulladdresses.shipping.town' => 'Shipping Town/City',
            'fulladdresses.shipping.county' => 'Shipping County/State',
            'fulladdresses.shipping.country' => 'Shipping Country',
            'fulladdresses.shipping.postcode' => 'Shipping Postcode',
            'fulladdresses.shipping.telephone' => 'Shipping Telephone',
            'fulladdresses.shipping.fax' => 'Shipping Fax',
            'deliveryaddress' => 'Delivery Address',
            'billingaddress' => 'Billing Address',
            'status' => 'Order Status',
        ];
    }

    public static function cartlinesFields(): array
    {
        return [
            'productid' => 'Product ID',
            'stock_code' => 'Stock Code',
            'product_name' => 'Product Name',
            'product_description' => 'Product Description',
            'qty' => 'Quantity',
            'price' => 'Unit Price (inc. VAT)',
            'price_exvat' => 'Unit Price (ex. VAT)',
            'disc' => 'Discount %',
            'sequence' => 'Line Sequence',
            'currency_code' => 'Currency Code',
        ];
    }

    public static function guessMapping(string $header): string
    {
        $norm = strtolower(preg_replace('/[\s\-_.]+/', '_', trim($header)));

        $hints = [
            'qty' => 'cartlines.qty',
            'quantity' => 'cartlines.qty',
            'sku' => 'cartlines.stock_code',
            'item_code' => 'cartlines.stock_code',
            'stock_code' => 'cartlines.stock_code',
            'product_name' => 'cartlines.product_name',
            'product' => 'cartlines.product_name',
            'description' => 'cartlines.product_description',
            'product_description' => 'cartlines.product_description',
            'unit_price' => 'cartlines.price',
            'price' => 'cartlines.price',
            'price_ex' => 'cartlines.price_exvat',
            'price_exvat' => 'cartlines.price_exvat',
            'discount' => 'cartlines.disc',
            'disc' => 'cartlines.disc',
            'currency' => 'cartlines.currency_code',
            'currency_code' => 'cartlines.currency_code',
            'account_code' => 'cartsbe.account_code',
            'account' => 'cartsbe.account_code',
            'order_number' => 'cartsbe.ordernumber',
            'ordernumber' => 'cartsbe.ordernumber',
            'order_no' => 'cartsbe.ordernumber',
            'order_ref' => 'cartsbe.ordernumber',
            'po' => 'cartsbe.porderref',
            'po_number' => 'cartsbe.porderref',
            'porderref' => 'cartsbe.porderref',
            'purchase_order' => 'cartsbe.porderref',
            'email' => 'cartsbe.email',
            'name' => 'cartsbe.name',
            'contact' => 'cartsbe.contact',
            'telephone' => 'cartsbe.telephone',
            'phone' => 'cartsbe.telephone',
            'postcode' => 'cartsbe.postcode',
            'delivery_address' => 'cartsbe.deliveryaddress',
            'deliveryaddress' => 'cartsbe.deliveryaddress',
            'billing_address' => 'cartsbe.billingaddress',
            'billingaddress' => 'cartsbe.billingaddress',
            'notes' => 'cartsbe.message',
            'message' => 'cartsbe.message',
            'delivery_notes' => 'cartsbe.delivery_notes',
            'shipping_method' => 'cartsbe.shippingmethod',
            'shippingmethod' => 'cartsbe.shippingmethod',
            'fulladdresses_shipping' => 'cartsbe.fulladdresses.shipping',
            'shipping_address_full' => 'cartsbe.fulladdresses.shipping',
            'full_shipping_address' => 'cartsbe.fulladdresses.shipping',
            'shipping_name' => 'cartsbe.fulladdresses.shipping.name',
            'shipping_firstname' => 'cartsbe.fulladdresses.shipping.firstname',
            'shipping_lastname' => 'cartsbe.fulladdresses.shipping.lastname',
            'shipping_company' => 'cartsbe.fulladdresses.shipping.companyname',
            'shipping_company_name' => 'cartsbe.fulladdresses.shipping.companyname',
            'shipping_contact' => 'cartsbe.fulladdresses.shipping.contact',
            'shipping_email' => 'cartsbe.fulladdresses.shipping.email',
            'shipping_address1' => 'cartsbe.fulladdresses.shipping.address1',
            'shipping_address2' => 'cartsbe.fulladdresses.shipping.address2',
            'shipping_address3' => 'cartsbe.fulladdresses.shipping.address3',
            'shipping_town' => 'cartsbe.fulladdresses.shipping.town',
            'shipping_city' => 'cartsbe.fulladdresses.shipping.town',
            'shipping_county' => 'cartsbe.fulladdresses.shipping.county',
            'shipping_state' => 'cartsbe.fulladdresses.shipping.county',
            'shipping_country' => 'cartsbe.fulladdresses.shipping.country',
            'shipping_postcode' => 'cartsbe.fulladdresses.shipping.postcode',
            'shipping_zip' => 'cartsbe.fulladdresses.shipping.postcode',
            'shipping_telephone' => 'cartsbe.fulladdresses.shipping.telephone',
            'shipping_phone' => 'cartsbe.fulladdresses.shipping.telephone',
            'shipping_fax' => 'cartsbe.fulladdresses.shipping.fax',
            'payment_method' => 'cartsbe.paymentmethod',
            'paymentmethod' => 'cartsbe.paymentmethod',
            'status' => 'cartsbe.status',
        ];

        return $hints[$norm] ?? '__skip__';
    }

    public function getConfiguredMappingProfiles(): array
    {
        $file = __DIR__ . self::CSV_MAP_CONFIG_PATH;
        if (!is_file($file)) {
            return [];
        }

        $config = require $file;
        if (!is_array($config)) {
            return [];
        }

        $profiles = $config['profiles'] ?? [];
        return is_array($profiles) ? $profiles : [];
    }

    public function detectMappingProfile(array $headers): ?array
    {
        $profiles = $this->getConfiguredMappingProfiles();
        if (empty($profiles) || empty($headers)) {
            return null;
        }

        $normalizedHeaders = [];
        foreach ($headers as $header) {
            $normalizedHeaders[$this->normalizeHeader((string) $header)] = (string) $header;
        }

        $bestMatch = null;
        $bestScore = -1;

        foreach ($profiles as $profileKey => $profile) {
            $columns = $profile['columns'] ?? [];
            if (!is_array($columns) || empty($columns)) {
                continue;
            }

            $normalizedColumns = [];
            foreach ($columns as $csvHeader => $targetField) {
                if (!is_string($csvHeader) || !is_string($targetField) || $targetField === '') {
                    continue;
                }
                $norm = $this->normalizeHeader($csvHeader);
                if (!isset($normalizedColumns[$norm])) {
                    $normalizedColumns[$norm] = $targetField;
                }
            }

            if (empty($normalizedColumns)) {
                continue;
            }

            $mapping = [];
            $matchedTargets = [];

            foreach ($normalizedHeaders as $normHeader => $originalHeader) {
                if (!isset($normalizedColumns[$normHeader])) {
                    continue;
                }

                $target = $normalizedColumns[$normHeader];
                $mapping[$originalHeader] = $target;
                $matchedTargets[$target] = true;
            }

            $matchedCount = count($mapping);
            $minMatchedColumns = (int) ($profile['minMatchedColumns'] ?? 3);
            if ($matchedCount < $minMatchedColumns) {
                continue;
            }

            $requiredTargets = $profile['requiredTargets'] ?? [];
            if (!is_array($requiredTargets)) {
                $requiredTargets = [];
            }

            $requiredOk = true;
            foreach ($requiredTargets as $requiredTarget) {
                if (!isset($matchedTargets[$requiredTarget])) {
                    $requiredOk = false;
                    break;
                }
            }

            if (!$requiredOk) {
                continue;
            }

            $requiredBonus = count($requiredTargets) * 100;
            $score = $requiredBonus + $matchedCount;
            if ($score <= $bestScore) {
                continue;
            }

            $bestScore = $score;
            $bestMatch = [
                'profileKey' => (string) $profileKey,
                'profileName' => (string) ($profile['name'] ?? $profileKey),
                'mapping' => $mapping,
                'matchedCount' => $matchedCount,
            ];
        }

        return $bestMatch;
    }

    public function convertRowsToOrders(array $rows): array
    {
        $orders = [];
        $skippedRows = [];

        foreach ($rows as $index => $row) {
            $lineNumber = $index + 2;
            $orderRef = $this->findValue($row, ['order_number', 'order_no', 'orderno', 'order_ref', 'orderid', 'order_id']);
            $sku = $this->findValue($row, ['sku', 'item', 'item_code', 'itemcode']);
            $qtyRaw = $this->findValue($row, ['qty', 'quantity']);

            if ($orderRef === '' || $sku === '' || $qtyRaw === '') {
                $skippedRows[] = [
                    'line' => $lineNumber,
                    'reason' => 'Missing required values: order reference, sku, or quantity.',
                    'row' => $row,
                ];
                continue;
            }

            $quantity = (int) $qtyRaw;
            if ($quantity <= 0) {
                $skippedRows[] = [
                    'line' => $lineNumber,
                    'reason' => 'Quantity must be greater than zero.',
                    'row' => $row,
                ];
                continue;
            }

            if (!isset($orders[$orderRef])) {
                $orders[$orderRef] = [
                    'orderRef' => $orderRef,
                    'customerRef' => $this->findValue($row, ['customer_ref', 'customer_reference', 'customer']),
                    'poNumber' => $this->findValue($row, ['po_number', 'po', 'purchase_order']),
                    'lines' => [],
                ];
            }

            $orders[$orderRef]['lines'][] = [
                'sku' => $sku,
                'quantity' => $quantity,
                'price' => $this->findValue($row, ['price', 'unit_price']),
                'raw' => $row,
            ];
        }

        return [
            'orders' => array_values($orders),
            'skippedRows' => $skippedRows,
        ];
    }

    public function convertRowsWithMapping(array $rows, array $mapping): array
    {
        $orders = [];
        $skippedRows = [];
        $targetMapping = $this->normalizeMappingToTarget($mapping);

        $orderKeyCol = null;
        $orderKeyPriority = ['cartsbe.ordernumber', 'cartsbe.porderref', 'cartsbe.account_code'];
        foreach ($orderKeyPriority as $priority) {
            if (isset($targetMapping[$priority]) && $targetMapping[$priority] !== '__skip__') {
                $orderKeyCol = $targetMapping[$priority];
                break;
            }
        }

        foreach ($rows as $index => $row) {
            $lineNumber = $index + 2;

            $groupKey = $orderKeyCol !== null && isset($row[$orderKeyCol])
                ? trim((string) $row[$orderKeyCol])
                : '';

            if ($groupKey === '') {
                $skippedRows[] = [
                    'line' => $lineNumber,
                    'reason' => 'Order identifier column is empty.',
                    'row' => $row,
                ];
                continue;
            }

            $cartsbeData = [];
            $cartlineData = [];

            foreach ($targetMapping as $target => $csvCol) {
                if (empty($target) || empty($csvCol) || $csvCol === '__skip__') {
                    continue;
                }

                [$model, $field] = explode('.', $target, 2);
                $value = isset($row[$csvCol]) ? trim((string) $row[$csvCol]) : '';

                if ($model === 'cartsbe') {
                    $cartsbeData[$field] = $value;
                } elseif ($model === 'cartlines') {
                    $cartlineData[$field] = $value;
                }
            }

            $qty = isset($cartlineData['qty']) ? (int) $cartlineData['qty'] : 0;
            if ($qty <= 0) {
                $skippedRows[] = [
                    'line' => $lineNumber,
                    'reason' => 'Quantity is zero or missing.',
                    'row' => $row,
                ];
                continue;
            }
            $cartlineData['qty'] = $qty;

            if (!isset($orders[$groupKey])) {
                $orders[$groupKey] = [
                    'groupKey' => $groupKey,
                    'cartsbe' => $cartsbeData,
                    'lines' => [],
                ];
            }

            $orders[$groupKey]['lines'][] = $cartlineData;
        }

        return [
            'orders' => array_values($orders),
            'skippedRows' => $skippedRows,
        ];
    }

    public function normalizeMappingToTarget(array $mapping): array
    {
        $targetMapping = [];

        foreach ($mapping as $key => $value) {
            if (!is_string($key) || !is_string($value)) {
                continue;
            }

            if (str_starts_with($key, 'cartsbe.') || str_starts_with($key, 'cartlines.')) {
                $targetMapping[$key] = $value;
                continue;
            }

            if (str_starts_with($value, 'cartsbe.') || str_starts_with($value, 'cartlines.')) {
                if (!isset($targetMapping[$value]) || $targetMapping[$value] === '__skip__') {
                    $targetMapping[$value] = $key;
                }
            }
        }

        return $targetMapping;
    }

    public function buildSummary(array $orders, array $skippedRows): array
    {
        $lineCount = 0;
        foreach ($orders as $order) {
            $lineCount += count($order['lines']);
        }

        return [
            'orderCount' => count($orders),
            'lineCount' => $lineCount,
            'skippedCount' => count($skippedRows),
        ];
    }

    public function importOrders(array $orders): array
    {
        $imported = 0;
        $errors = [];

        foreach ($orders as $order) {
            try {
                Yii::warning([
                    'message' => 'QVC order import approved',
                    'order' => $order,
                ], 'qvc.order.import');

                $imported++;
            } catch (\Throwable $e) {
                $errors[] = [
                    'orderRef' => $order['orderRef'] ?? 'unknown',
                    'error' => $e->getMessage(),
                ];
            }
        }

        if (!empty($errors)) {
            return [
                'success' => false,
                'message' => sprintf('Imported %d orders, %d failed.', $imported, count($errors)),
                'errors' => $errors,
            ];
        }

        return [
            'success' => true,
            'message' => sprintf('Successfully imported %d orders.', $imported),
            'errors' => [],
        ];
    }

    public function importMappedOrders(array $orders): array
    {
        $imported = 0;
        $errors = [];

        foreach ($orders as $order) {
            $db = Yii::$app->db;
            $transaction = $db->beginTransaction();

            try {
                $cartsbe = new \PortalPeople\qvc\models\Cart();
                $nestedCartsbeData = [];

                foreach ($order['cartsbe'] as $field => $value) {
                    if (strpos($field, '.') !== false) {
                        $fieldPath = array_values(array_filter(explode('.', $field), static function ($segment) {
                            return $segment !== '';
                        }));

                        if (!empty($fieldPath)) {
                            $this->setNestedArrayValue($nestedCartsbeData, $fieldPath, $value);
                        }
                        continue;
                    }

                    if ($cartsbe->hasAttribute($field)) {
                        $cartsbe->$field = $value;
                    }
                }

                foreach ($nestedCartsbeData as $rootField => $nestedValues) {
                    if (!$cartsbe->hasAttribute($rootField)) {
                        continue;
                    }

                    $existingValue = $cartsbe->$rootField;
                    $normalizedValue = [];

                    if (is_string($existingValue) && trim($existingValue) !== '') {
                        $decoded = json_decode($existingValue, true);
                        if (is_array($decoded)) {
                            $normalizedValue = $decoded;
                        }
                    } elseif (is_array($existingValue)) {
                        $normalizedValue = $existingValue;
                    }

                    $cartsbe->$rootField = json_encode(
                        $this->mergeNestedArrays($normalizedValue, $nestedValues),
                        JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
                    );
                }

                $cartsbe->nooflines = count($order['lines']);
                
                $cartsbe->dateordered = strtotime('now');
                $cartsbe->status = 'Paid';
                if (!$cartsbe->save()) {
                    throw new \RuntimeException(
                        'Cartsbe save failed: ' . implode('; ', array_map(
                            static fn($msgs) => implode(', ', $msgs),
                            $cartsbe->getErrors()
                        ))
                    );
                }

                foreach ($order['lines'] as $lineData) {
                    $cartline = new \PortalPeople\qvc\models\Cartlines();
                    $cartline->basketid = $cartsbe->id;

                    foreach ($lineData as $field => $value) {
                        if ($cartline->hasAttribute($field)) {
                            $cartline->$field = $value;
                        }
                    }
                    $cartline->dispatch = 0;
                    $cartline->requested_date = date('Y-m-d', strtotime('+3 days'));

                    if (!$cartline->product && !empty($cartline->stock_code)) {
                        $product = \backend\models\Productsbe::find()->where(['stock_code' => $cartline->stock_code])->one();
                        if ($product) {
                            $qvc =$product->data['qvc'];
                            $cartline->productid = $product->id;
                            $cartline->product_description = $qvc?->name ?? $cartline->product_description;
                            $cdata = $cartline->data;
                            $cdata['qvc'] = [
                                'hauliers' => $qvc?->haulierid ?? null,
                                'haulierid' => !empty($qvc?->haulierid) && count($qvc?->haulierid) == 1 ? $qvc?->haulierid[0] : null ,
                            ];
                            Yii::warning(!empty($qvc?->haulierid) && count($qvc?->haulierid) == 1 ? $qvc?->haulierid[0] : null , 'qvc.import.haulierid');
                            $cartline->haulierint = !empty($qvc?->haulierid) && count($qvc?->haulierid) == 1 ? $qvc?->haulierid[0] : null ;
                            $cartline->data = $cdata;
                        }
                    }

                    if (!$cartline->save()) {
                        throw new \RuntimeException(
                            'Cartlines save failed: ' . implode('; ', array_map(
                                static fn($msgs) => implode(', ', $msgs),
                                $cartline->getErrors()
                            ))
                        );
                    }
                }

                $transaction->commit();
                $imported++;
            } catch (\Throwable $e) {
                $transaction->rollBack();
                $errors[] = [
                    'groupKey' => $order['groupKey'] ?? 'unknown',
                    'error' => $e->getMessage(),
                ];
                Yii::error([
                    'message' => 'QVC mapped import failed',
                    'groupKey' => $order['groupKey'] ?? 'unknown',
                    'error' => $e->getMessage(),
                    'line' => $e->getLine(),
                    'file' => $e->getFile(),
                ], 'qvc.mapped.import');
            }
        }

        if (!empty($errors)) {
            return [
                'success' => false,
                'message' => sprintf('Imported %d orders, %d failed.', $imported, count($errors)),
                'errors' => $errors,
            ];
        }

        return [
            'success' => true,
            'message' => sprintf(
                'Successfully imported %d orders (%d lines total).',
                $imported,
                array_sum(array_map(static fn($o) => count($o['lines']), $orders))
            ),
            'errors' => [],
        ];
    }

    private function findValue(array $row, array $aliases): string
    {
        foreach ($aliases as $alias) {
            foreach ($row as $key => $value) {
                if ($this->normalizeHeader((string) $key) === $this->normalizeHeader($alias)) {
                    return trim((string) $value);
                }
            }
        }

        return '';
    }

    private function normalizeHeader(string $header): string
    {
        return strtolower(str_replace([' ', '-', '.'], '_', trim($header)));
    }

    public function loadGlobalMapping(): array
    {
        $settings = $this->findGlobalMappingRecord();
        if ($settings === null) {
            return [];
        }

        $data = $this->decodeSettingsData($settings->data);
        $encrypted = $data[self::GLOBAL_MAPPING_DATA_KEY] ?? null;
        if (!is_string($encrypted) || $encrypted === '') {
            return [];
        }

        try {
            $decrypted = Yii::$app->security->decryptByKey(
                base64_decode($encrypted),
                Yii::$app->params['settings']['seckey']
            );

            if (!is_string($decrypted) || $decrypted === '') {
                return [];
            }

            $mapping = Json::decode($decrypted, true);
            return is_array($mapping) ? $mapping : [];
        } catch (\Throwable $e) {
            Yii::warning([
                'message' => 'Unable to decrypt global QVC CSV mapping',
                'error' => $e->getMessage(),
            ], 'qvc.mapping.global');
            return [];
        }
    }

    public function saveGlobalMapping(array $mapping): bool
    {
        $settings = $this->findGlobalMappingRecord();

        $normalizedMapping = [];
        foreach ($mapping as $header => $target) {
            if (!is_string($header) || !is_string($target) || $target === '') {
                continue;
            }
            $normalizedMapping[$header] = $target;
        }

        try {
            $payload = Json::encode($normalizedMapping);
            $encrypted = base64_encode(
                Yii::$app->security->encryptByKey(
                    $payload,
                    Yii::$app->params['settings']['seckey']
                )
            );
        } catch (\Throwable $e) {
            Yii::error([
                'message' => 'Unable to encrypt global QVC CSV mapping',
                'error' => $e->getMessage(),
            ], 'qvc.mapping.global');
            return false;
        }

        $data = $this->decodeSettingsData($settings->data);
        $data[self::GLOBAL_MAPPING_DATA_KEY] = $encrypted;
        $settings->data = Json::encode($data);

        if ($settings->isNewRecord) {
            if (!$settings->save()) {
                Yii::error([
                    'message' => 'Unable to create global QVC CSV mapping row',
                    'errors' => $settings->getErrors(),
                ], 'qvc.mapping.global');
                return false;
            }

            return true;
        }

        if (!$settings->save(false, ['data'])) {
            Yii::error([
                'message' => 'Unable to save global QVC CSV mapping',
                'settingsId' => $settings->id,
                'errors' => $settings->getErrors(),
            ], 'qvc.mapping.global');
            return false;
        }

        return true;
    }

    private function findGlobalMappingRecord(): ?Globalsettingsbe
    {
        $centerId = $this->resolveCenterId();

        $query = Globalsettingsbe::find()
            ->where([
                'name' => self::GLOBAL_MAPPING_SETTING_NAME,
                'type' => self::GLOBAL_MAPPING_SETTING_TYPE,
            ])
            ->andWhere(['status' => 'Active']);

        if ($centerId !== null) {
            $query->andWhere(['centerid' => $centerId]);
        }

        $record = $query
            ->orderBy(['updated_at' => SORT_DESC, 'created_at' => SORT_DESC])
            ->one();

        if ($record !== null) {
            return $record;
        }

        if ($centerId !== null) {
            $fallback = Globalsettingsbe::find()
                ->where([
                    'name' => self::GLOBAL_MAPPING_SETTING_NAME,
                    'type' => self::GLOBAL_MAPPING_SETTING_TYPE,
                ])
                ->andWhere(['status' => 'Active'])
                ->orderBy(['updated_at' => SORT_DESC, 'created_at' => SORT_DESC])
                ->one();

            if ($fallback !== null) {
                return $fallback;
            }
        }

        return new Globalsettingsbe([
            'id' => Base::Tempid(),
            'language' => 'en',
            'status' => 'Active',
            'name' => self::GLOBAL_MAPPING_SETTING_NAME,
            'type' => self::GLOBAL_MAPPING_SETTING_TYPE,
            'centerid' => $centerId,
            'setting' => 'Encrypted global CSV mapping for QVC importer',
            'data' => '{}',
        ]);
    }

    private function resolveCenterId(): ?string
    {
        $centerId = Yii::$app->params['settings']['id'] ?? null;
        if (!is_string($centerId) || $centerId === '') {
            return null;
        }

        return $centerId;
    }

    private function decodeSettingsData($rawData): array
    {
        if (is_array($rawData)) {
            return $rawData;
        }

        if (is_object($rawData)) {
            return (array) $rawData;
        }

        if (is_string($rawData) && trim($rawData) !== '') {
            $decoded = Json::decode($rawData, true);
            if (is_array($decoded)) {
                return $decoded;
            }
        }

        return [];
    }

    private function setNestedArrayValue(array &$target, array $path, $value): void
    {
        $cursor = &$target;
        $lastIndex = count($path) - 1;

        foreach ($path as $index => $segment) {
            if ($index === $lastIndex) {
                $cursor[$segment] = $value;
                return;
            }

            if (!isset($cursor[$segment]) || !is_array($cursor[$segment])) {
                $cursor[$segment] = [];
            }

            $cursor = &$cursor[$segment];
        }
    }

    private function mergeNestedArrays(array $base, array $override): array
    {
        foreach ($override as $key => $value) {
            if (isset($base[$key]) && is_array($base[$key]) && is_array($value)) {
                $base[$key] = $this->mergeNestedArrays($base[$key], $value);
            } else {
                $base[$key] = $value;
            }
        }

        return $base;
    }
}
