<?php

if (! defined('ABSPATH')) {
    exit;
} class PufferGo_Template_Config
{
    public const ROUTE_NAMESPACE = 'puffergo/v1';

    public const ROUTE_PATH = '/template-config';

    public const OPTION_PREFIX = 'puffergo_template_config_';

    private static $catalog_cache = null;

    public function __construct()
    {
        add_action('rest_api_init', array($this, 'register_routes'));
    }

    public function register_routes()
    {
        register_rest_route(self::ROUTE_NAMESPACE, self::ROUTE_PATH, array(array('methods' => 'GET', 'callback' => array($this, 'rest_get'), 'permission_callback' => function () { return current_user_can('manage_options'); }, 'args' => array('layout' => array('required' => true, 'sanitize_callback' => 'sanitize_key'), 'variant' => array('required' => false, 'sanitize_callback' => 'sanitize_key'), ), ), array('methods' => 'POST', 'callback' => array($this, 'rest_post'), 'permission_callback' => function () { return current_user_can('manage_options'); }, 'args' => array('layout' => array('required' => true, 'sanitize_callback' => 'sanitize_key'), 'variant' => array('required' => false, 'sanitize_callback' => 'sanitize_key'), ), ), ));
    }

    public function rest_get(WP_REST_Request $request)
    {
        $layout = (string) $request->get_param('layout');
        $variant = (string) $request->get_param('variant');

        if ('' === $variant) {
            $variant = self::resolve_active_variant($layout);
        } $schema = self::resolve_schema($layout, $variant);

        if (null === $schema) {
            return new WP_Error('puffergo_no_schema', __('No configurable schema for this layout/variant.', 'puffergo'), array('status' => 404));
        }

return rest_ensure_response(array('layout' => $layout, 'variant' => $variant, 'schema' => $schema, 'values' => self::read_values($layout, $variant), ));
    }

    public function rest_post(WP_REST_Request $request)
    {
        $layout = (string) $request->get_param('layout');
        $variant = (string) $request->get_param('variant');

        if ('' === $variant) {
            $variant = self::resolve_active_variant($layout);
        } $schema = self::resolve_schema($layout, $variant);

        if (null === $schema) {
            return new WP_Error('puffergo_no_schema', __('No configurable schema for this layout/variant.', 'puffergo'), array('status' => 404));
        } $body = $request->get_json_params();
        $incoming = is_array($body) ? $body : array();
        $values = self::sanitize_payload($schema, $incoming);
        $store = self::read_store($layout);
        $store[ $variant ] = $values;
        update_option(self::OPTION_PREFIX . $layout, wp_json_encode($store));

        return rest_ensure_response(array('success' => true, 'layout' => $layout, 'variant' => $variant, 'values' => $values, ));
    }

    public static function load_catalog()
    {
        if (null !== self::$catalog_cache) {
            return self::$catalog_cache;
        } self::$catalog_cache = array('schemaVersion' => 1, 'capabilities' => array());
        $path = PUFFERGO_PLUGIN_DIR . '/config/capabilities.json';

        if (! is_readable($path)) {
            return self::$catalog_cache;
        } $raw = file_get_contents($path);

        if (false === $raw) {
            return self::$catalog_cache;
        } $decoded = json_decode($raw, true);

        if (is_array($decoded)) {
            self::$catalog_cache = $decoded;
        }

return self::$catalog_cache;
    }

    private static function get_variant_meta($layout, $variant)
    {
        if ('' === $layout || '' === $variant) {
            return null;
        }

if (! class_exists('PufferGo_Template_Loader')) {
            return null;
        } $variants = PufferGo_Template_Loader::get_content_templates($layout);

        if (empty($variants) || ! isset($variants[ $variant ])) {
            return null;
        } $entry = $variants[ $variant ];
        $uses = (isset($entry['uses']) && is_array($entry['uses'])) ? array_values($entry['uses']) : array();
        $defaults = (isset($entry['defaults']) && is_array($entry['defaults'])) ? $entry['defaults'] : array();

        return array('uses' => $uses, 'defaults' => $defaults);
    }

    public static function resolve_schema($layout, $variant)
    {
        $meta = self::get_variant_meta($layout, $variant);

        if (null === $meta || empty($meta['uses'])) {
            return null;
        } $catalog = self::load_catalog();
        $capabilities = isset($catalog['capabilities']) && is_array($catalog['capabilities']) ? $catalog['capabilities'] : array();
        $effective = array();

        foreach ($meta['uses'] as $cap_id) {
            $cap_id = sanitize_key((string) $cap_id);

            if ('' === $cap_id || ! isset($capabilities[ $cap_id ])) {
                continue;
            } $cap = $capabilities[ $cap_id ];
            $fields = (isset($cap['fields']) && is_array($cap['fields'])) ? $cap['fields'] : array();
            $override = (isset($meta['defaults'][ $cap_id ]) && is_array($meta['defaults'][ $cap_id ])) ? $meta['defaults'][ $cap_id ] : array();
            $merged_fields = array();

            foreach ($fields as $field) {
                if (! is_array($field) || empty($field['key']) || empty($field['type'])) {
                    continue;
                } $key = (string) $field['key'];

                if (array_key_exists($key, $override)) {
                    $field['default'] = $override[ $key ];
                } $merged_fields[] = $field;
            } $entry = array('id' => $cap_id, 'kind' => isset($cap['kind']) ? (string) $cap['kind'] : 'content', 'label' => isset($cap['label']) ? (string) $cap['label'] : $cap_id, 'fields' => $merged_fields, );

            if (isset($cap['cssVarMap'][ $layout ]) && is_array($cap['cssVarMap'][ $layout ])) {
                $entry['cssVarMap'] = $cap['cssVarMap'][ $layout ];
            }

if (isset($cap['presets']) && is_array($cap['presets'])) {
                $entry['presets'] = $cap['presets'];
            } $effective[] = $entry;
        }

if (empty($effective)) {
            return null;
        }

return array('schemaVersion' => isset($catalog['schemaVersion']) ? absint($catalog['schemaVersion']) : 1, 'layout' => $layout, 'variant' => $variant, 'capabilities' => $effective, );
    }

    private static function read_store($layout)
    {
        $raw = get_option(self::OPTION_PREFIX . $layout, '');

        if ('' === $raw) {
            return array();
        } $decoded = json_decode((string) $raw, true);

        if (! is_array($decoded)) {
            return array();
        }

foreach ($decoded as $variant_slot) {
            if (! is_array($variant_slot)) {
                return array();
            }

foreach ($variant_slot as $cap_slot) {
                if (! is_array($cap_slot)) {
                    return array();
                }
            }
        }

return $decoded;
    }

    public static function read_values($layout, $variant)
    {
        $schema = self::resolve_schema($layout, $variant);

        if (null === $schema) {
            return array();
        } $store = self::read_store($layout);
        $variant_store = isset($store[ $variant ]) && is_array($store[ $variant ]) ? $store[ $variant ] : array();
        $out = array();

        foreach ($schema['capabilities'] as $cap) {
            $cap_id = $cap['id'];
            $cap_stored = isset($variant_store[ $cap_id ]) && is_array($variant_store[ $cap_id ]) ? $variant_store[ $cap_id ] : array();
            $cap_values = array();

            foreach ($cap['fields'] as $field) {
                $key = $field['key'];
                $type = isset($field['type']) ? (string) $field['type'] : '';

                if (! array_key_exists($key, $cap_stored)) {
                    $cap_values[ $key ] = self::default_for_field($field);
                    continue;
                } $stored = $cap_stored[ $key ];

                if ('image' === $type && self::is_image_unset($stored)) {
                    $cap_values[ $key ] = self::default_for_field($field);
                } else {
                    $cap_values[ $key ] = $stored;
                }
            } $out[ $cap_id ] = $cap_values;
        }

return $out;
    }

    private static function is_image_unset($value)
    {
        if (! is_array($value)) {
            return true;
        } $url = isset($value['url']) ? (string) $value['url'] : '';

        return '' === trim($url);
    }

    public static function sanitize_payload($schema, $payload)
    {
        $payload = is_array($payload) ? $payload : array();
        $out = array();

        foreach ($schema['capabilities'] as $cap) {
            $cap_id = $cap['id'];
            $incap = isset($payload[ $cap_id ]) && is_array($payload[ $cap_id ]) ? $payload[ $cap_id ] : array();
            $cap_out = array();

            foreach ($cap['fields'] as $field) {
                $key = $field['key'];
                $raw = array_key_exists($key, $incap) ? $incap[ $key ] : null;
                $cap_out[ $key ] = self::sanitize_field($field, $raw);
            } $out[ $cap_id ] = $cap_out;
        }

return $out;
    }

    public static function default_for_field($field)
    {
        if (array_key_exists('default', $field)) {
            return $field['default'];
        }

switch ($field['type']) {
            case 'image': return array('id' => 0, 'url' => '');
            case 'select': if (isset($field['options']) && is_array($field['options']) && ! empty($field['options'])) {
                $first = reset($field['options']);

                if (is_array($first) && isset($first['value'])) {
                    return (string) $first['value'];
                }
            }

return '';
            case 'color': case 'text': case 'textarea': case 'url': default: return '';
        }
    }

    public static function sanitize_field($field, $raw)
    {
        $type = isset($field['type']) ? (string) $field['type'] : '';

        switch ($type) {
            case 'text': return sanitize_text_field(is_scalar($raw) ? (string) $raw : '');
            case 'textarea': return sanitize_textarea_field(is_scalar($raw) ? (string) $raw : '');
            case 'url': return esc_url_raw(is_scalar($raw) ? (string) $raw : '');
            case 'color': $clean = self::sanitize_color_value(is_scalar($raw) ? (string) $raw : '');

                return false === $clean ? '' : $clean;
            case 'select': $candidate = is_scalar($raw) ? (string) $raw : '';
                $allowed = array();

                if (isset($field['options']) && is_array($field['options'])) {
                    foreach ($field['options'] as $opt) {
                        if (is_array($opt) && isset($opt['value'])) {
                            $allowed[] = (string) $opt['value'];
                        }
                    }
                }

if (in_array($candidate, $allowed, true)) {
                    return $candidate;
                }

return self::default_for_field($field);
            case 'image': $id = 0;
                $url = '';

                if (is_array($raw)) {
                    $id = absint($raw['id'] ?? 0);
                    $url = esc_url_raw((string) ($raw['url'] ?? ''));
                }

return array('id' => $id, 'url' => $url);
            default: return null;
        }
    }

    public static function sanitize_color_value($v)
    {
        $v = trim((string) $v);

        if ('' === $v) {
            return false;
        }

if (strlen($v) > 500) {
            return false;
        }

if (preg_match('/[;{}<>]/u', $v)) {
            return false;
        }

if (function_exists('sanitize_hex_color')) {
            $h = sanitize_hex_color($v);

            if (is_string($h) && '' !== $h) {
                return $h;
            }
        }

if (preg_match('/^(?:color-mix|color\(|oklch|oklab|hsl|hsla|rgb|rgba|var)\s*\(/i', $v) || 'transparent' === strtolower($v)) {
            return $v;
        }

if (preg_match('/^#[0-9A-Fa-f]{3,8}$/', $v)) {
            return $v;
        }

return false;
    }

    public static function get_capability_values($layout, $capability_id)
    {
        $variant = self::resolve_active_variant($layout);
        $values = self::read_values($layout, $variant);

        return isset($values[ $capability_id ]) && is_array($values[ $capability_id ]) ? $values[ $capability_id ] : array();
    }

    public static function resolve_active_variant($layout)
    {
        if ('' === $layout || ! class_exists('PufferGo_Template_Loader')) {
            return '';
        }

if ('header' === $layout && method_exists('PufferGo_Template_Loader', 'get_active_header')) {
            return (string) PufferGo_Template_Loader::get_active_header();
        }

if ('footer' === $layout && method_exists('PufferGo_Template_Loader', 'get_active_footer')) {
            return (string) PufferGo_Template_Loader::get_active_footer();
        }

if (method_exists('PufferGo_Template_Loader', 'get_active_content_template')) {
            return (string) PufferGo_Template_Loader::get_active_content_template($layout);
        }

return '';
    }

    public static function build_css_var_map($layout, $variant)
    {
        $schema = self::resolve_schema($layout, $variant);

        if (null === $schema) {
            return array();
        } $values = self::read_values($layout, $variant);
        $out = array();

        foreach ($schema['capabilities'] as $cap) {
            if (($cap['kind'] ?? '') !== 'tokens') {
                continue;
            } $cap_values = isset($values[ $cap['id'] ]) && is_array($values[ $cap['id'] ]) ? $values[ $cap['id'] ] : array();

            if (! empty($cap['cssVarMap']) && is_array($cap['cssVarMap'])) {
                foreach ($cap['cssVarMap'] as $field_key => $css_var) {
                    if (! isset($cap_values[ $field_key ])) {
                        continue;
                    } $val = $cap_values[ $field_key ];

                    if (! is_string($val) || '' === $val) {
                        continue;
                    } $out[ (string) $css_var ] = $val;
                }
            }

foreach ($cap['fields'] as $field) {
                if (empty($field['cssVarValueMap']) || ! is_array($field['cssVarValueMap'])) {
                    continue;
                } $layout_map = $field['cssVarValueMap'][ $layout ] ?? null;

                if (! is_array($layout_map)) {
                    continue;
                } $field_key = $field['key'];
                $field_value = isset($cap_values[ $field_key ]) ? (string) $cap_values[ $field_key ] : '';

                if ('' === $field_value || ! isset($layout_map[ $field_value ]) || ! is_array($layout_map[ $field_value ])) {
                    continue;
                }

foreach ($layout_map[ $field_value ] as $css_var => $css_value) {
                    $out[ (string) $css_var ] = (string) $css_value;
                }
            }
        }

return $out;
    }

    public static function print_header_style_block($variant)
    {
        $map = self::build_css_var_map('header', $variant);

        if (empty($map)) {
            return;
        } $parts = array();

        foreach ($map as $prop => $val) {
            $parts[] = esc_attr($prop) . ': ' . esc_attr($val) . ' !important';
        } $v_id = esc_attr((string) $variant);
        $css = '.puffergo-header-wrap.puffergo-header-active[data-header-template="' . $v_id . '"] > header{ ' . implode(';', $parts) . '; }';
        echo '<style id="puffergo-header-appearance">';
        echo $css;
        echo '</style>';
    }
} new PufferGo_Template_Config();
function puffergo_get_template_config_values($layout)
{
    $layout = sanitize_key((string) $layout);

    if ('' === $layout) {
        return array();
    } $variant = PufferGo_Template_Config::resolve_active_variant($layout);

    if ('' === $variant) {
        return array();
    }

return PufferGo_Template_Config::read_values($layout, $variant);
}
