<?php

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedNamespaceFound -- APD is the established namespace shared with the Pro add-on and retained for backward compatibility.
namespace APD\Domain\Config;

use APD\Support\Json;
use APD\Support\RuntimeDataSchema;

defined('ABSPATH') || exit;

class ConfigNormalizer
{
    public function normalize(array $config) : array
    {
        $colorsPayload = RuntimeDataSchema::sanitizeProductColorsConfig($this->decode($config['_apd_colors'] ?? '{}'));
        $fontsPayload = RuntimeDataSchema::sanitizeProductFontsConfig($this->decode($config['_apd_fonts'] ?? '{}'));
        $pricingPayload = RuntimeDataSchema::sanitizeProductPricingConfig($this->decode($config['_apd_pricing_rules'] ?? '{}'));
        $assetFilters = RuntimeDataSchema::sanitizeProductAssetFilters($this->decode($config['_apd_asset_filters'] ?? '{}'));

        return [
            'schemaVersion' => RuntimeDataSchema::VERSION,
            'colorsConfig' => $colorsPayload,
            'theme' => $this->decode($config['_apd_theme'] ?? '{}'),
            'layout' => $this->decode($config['_apd_layout'] ?? '{}'),
            'permissions' => $this->decode($config['_apd_permissions'] ?? '{}'),
            'moduleConfig' => $this->decode($config['_apd_modules'] ?? '{}'),
            'views' => $this->decode($config['_apd_views'] ?? '[]'),
            'drawingZones' => $this->decode($config['_apd_drawing_zones'] ?? '[]'),
            'fonts' => $this->flattenFonts($fontsPayload),
            'upload' => $this->decode($config['_apd_upload'] ?? '{}'),
            'pricing' => $pricingPayload,
            'colors' => (array) ($colorsPayload['items'] ?? []),
            'printingMethods' => (array) ($colorsPayload['printingMethods'] ?? []),
            'catalog' => [
                'colors' => (array) ($colorsPayload['items'] ?? []),
                'printingMethods' => (array) ($colorsPayload['printingMethods'] ?? []),
            ],
            'integrations' => [
                'selectionMenu' => $this->decode($config['_apd_selection_menu'] ?? '{}'),
                'frontBehavior' => $this->decode($config['_apd_front_behavior'] ?? '{}'),
                'mobileBehavior' => $this->decode($config['_apd_mobile_behavior'] ?? '{}'),
            ],
            'selectionMenu' => $this->decode($config['_apd_selection_menu'] ?? '{}'),
            'frontBehavior' => $this->decode($config['_apd_front_behavior'] ?? '{}'),
            'mobileBehavior' => $this->decode($config['_apd_mobile_behavior'] ?? '{}'),
            'ui' => $this->normalizeUiConfig($this->decode($config['_apd_ui'] ?? '{}')),
            'initialDocument' => $this->decode($config['_apd_initial_document'] ?? '{}'),
            'initialState' => $this->decode($config['_apd_initial_state'] ?? '{}'),
            'assetFilters' => $assetFilters,
            'context' => [
                'configId' => isset($config['ID']) ? (int) $config['ID'] : null,
            ],
        ];
    }

    protected function decode(string $value) : mixed
    {
        $trimmed = trim((string) $value);
        if ($trimmed === '') {
            return [];
        }

        if ($trimmed === 'null') {
            return null;
        }

        return Json::decode((string) $value, []);
    }

    protected function normalizeUiConfig(mixed $payload) : array
    {
        if (! is_array($payload)) {
            return [];
        }

        $ui = $payload;
        $allowedModes = ['auto', 'thumbnails', 'dots', 'numbers'];

        if (array_key_exists('historyControls', $ui)) {
            if ($ui['historyControls'] === false) {
                $ui['historyControls'] = false;
            } elseif (is_array($ui['historyControls'])) {
                $controls = $ui['historyControls'];
                $ui['historyControls'] = [
                    'undo' => ($controls['undo'] ?? true) !== false,
                    'redo' => ($controls['redo'] ?? true) !== false,
                    'reset' => ($controls['reset'] ?? true) !== false,
                ];
            } else {
                unset($ui['historyControls']);
            }
        }

        if (array_key_exists('viewsPagination', $ui) && $ui['viewsPagination'] === false) {
            $ui['viewsPagination'] = false;
            $ui['viewsPaginationEnabled'] = false;
            unset($ui['viewsPaginationMode']);
            return $ui;
        }

        if (array_key_exists('viewsPaginationEnabled', $ui)) {
            $ui['viewsPaginationEnabled'] = (bool) $ui['viewsPaginationEnabled'];
            if (! $ui['viewsPaginationEnabled']) {
                $ui['viewsPagination'] = false;
                unset($ui['viewsPaginationMode']);
                return $ui;
            }
        }

        $mode = '';
        if (isset($ui['viewsPagination']) && is_array($ui['viewsPagination']) && isset($ui['viewsPagination']['mode'])) {
            $mode = sanitize_key((string) $ui['viewsPagination']['mode']);
        } elseif (isset($ui['viewsPaginationMode'])) {
            $mode = sanitize_key((string) $ui['viewsPaginationMode']);
        }

        if ($mode !== '') {
            if (! in_array($mode, $allowedModes, true)) {
                unset($ui['viewsPagination'], $ui['viewsPaginationMode'], $ui['viewsPaginationEnabled']);
                return $ui;
            }
            $ui['viewsPagination'] = [
                'enabled' => true,
                'mode' => $mode,
            ];
            $ui['viewsPaginationMode'] = $mode;
            $ui['viewsPaginationEnabled'] = true;
        }

        return $ui;
    }

    protected function flattenFonts(array $payload) : array
    {
        $items = [];
        foreach (['system', 'google', 'custom'] as $source) {
            foreach ((array) ($payload[$source] ?? []) as $font) {
                if (is_array($font)) {
                    $font['source'] = $source;
                    $items[] = $font;
                }
            }
        }

        return $items;
    }
}
