<?php

if (! defined('ABSPATH')) {
    exit;
} class PufferGo_Design_System
{
    public const OPTION_KEY = 'puffergo_design_system';

    public const OVERRIDES = array('canvasWidth' => array('label' => 'Content width', 'options' => array('80rem' => array('label' => '1280px', 'vars' => array('--pg-canvas-width' => '80rem')), '90rem' => array('label' => '1440px', 'vars' => array('--pg-canvas-width' => '90rem')), '100rem' => array('label' => '1600px (default)', 'vars' => array('--pg-canvas-width' => '100rem')), ), ), );

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

    public function register_rest_routes()
    {
        register_rest_route('puffergo/v1', '/design-system', array(array('methods' => 'GET', 'callback' => array($this, 'rest_get'), 'permission_callback' => function () { return current_user_can('edit_posts'); }, ), array('methods' => 'POST', 'callback' => array($this, 'rest_save'), 'permission_callback' => function () { return current_user_can('edit_posts'); }, ), ));
        register_rest_route('puffergo/v1', '/design-system/overrides', array(array('methods' => 'GET', 'callback' => array($this, 'rest_get_overrides'), 'permission_callback' => function () { return current_user_can('edit_posts'); }, ), array('methods' => 'POST', 'callback' => array($this, 'rest_save_overrides'), 'permission_callback' => function () { return current_user_can('edit_theme_options'); }, ), ));
        register_rest_route('puffergo/v1', '/design-system/generate', array('methods' => 'POST', 'callback' => array($this, 'rest_generate'), 'permission_callback' => function () { return current_user_can('edit_posts'); }, ));
    }

    public function rest_generate($request)
    {
        $params = $request->get_json_params();
        $model = isset($params['model']) ? sanitize_text_field(wp_unslash($params['model'])) : 'deepseek-v3';
        $hint = isset($params['userHint']) ? sanitize_textarea_field(wp_unslash($params['userHint'])) : '';
        $bc_raw = isset($params['brandContext']) && is_array($params['brandContext']) ? $params['brandContext'] : array();
        $preset_id = isset($params['presetId']) ? sanitize_text_field(wp_unslash($params['presetId'])) : '';
        $ai_scene = isset($params['aiScene']) && is_string($params['aiScene']) ? sanitize_text_field(wp_unslash($params['aiScene'])) : '';

        if (! empty($preset_id)) {
            try {
                $client = PufferGo_API_Client::get_instance();
                $result = $client->post('/api/ai/generate-design-tokens', array('presetId' => $preset_id), array('timeout' => 30, 'log_prefix' => 'DesignSystem Preset'));
                $raw_schemes = isset($result['schemes']) && is_array($result['schemes']) ? $result['schemes'] : array();

                if (empty($raw_schemes)) {
                    return new WP_REST_Response(array('success' => false, 'message' => esc_html__('Preset not found.', 'puffergo'), ), 404);
                } $s = $raw_schemes[0];
                $s['id'] = 'preset_' . sanitize_key($preset_id);
                $s['generatedAt'] = gmdate('c');
                $s['isCustom'] = false;
                $scheme = $this->sanitize_scheme($s);
                $valid = $this->validate_scheme_complete($scheme);

                if (is_wp_error($valid)) {
                    return new WP_REST_Response(array('success' => false, 'code' => $valid->get_error_code(), 'message' => $valid->get_error_message(), ), 400);
                }

return new WP_REST_Response(array('success' => true, 'data' => array('schemes' => array($scheme), 'activeSchemeId' => $scheme['id'], ), ), 200);
            } catch (PufferGo_API_Exception $e) {
                return new WP_REST_Response($e->toArray(), $e->getCode());
            } catch (Exception $e) {
                return new WP_REST_Response(array('success' => false, 'message' => $e->getMessage()), 500);
            }
        } $brand_context = array('name' => sanitize_text_field($bc_raw['name'] ?? ''), 'industry' => sanitize_text_field($bc_raw['industry'] ?? ''), 'products' => sanitize_text_field($bc_raw['products'] ?? ''), 'audience' => sanitize_text_field($bc_raw['audience'] ?? ''), 'tone' => sanitize_text_field($bc_raw['tone'] ?? ''), );

        try {
            $client = PufferGo_API_Client::get_instance();
            $design_tokens_body = array('brandContext' => $brand_context, 'userHint' => $hint ?: null, 'model' => $model, );

            if (! empty($ai_scene)) {
                $design_tokens_body['aiScene'] = $ai_scene;
            } $result = $client->post('/api/ai/generate-design-tokens', $design_tokens_body, array('timeout' => 120, 'log_prefix' => 'DesignSystem Generate'));
            $raw_schemes = isset($result['schemes']) && is_array($result['schemes']) ? $result['schemes'] : array();

            if (empty($raw_schemes)) {
                return new WP_REST_Response(array('success' => false, 'message' => esc_html__('AI did not return a design scheme. Please try again.', 'puffergo'), ), 500);
            } $ts = round(microtime(true) * 1000);
            $new_schemes = array();

            foreach ($raw_schemes as $i => $s) {
                $clean = $this->sanitize_scheme(array_merge($s, array('id' => 'scheme_' . $ts . '_' . $i, 'generatedAt' => gmdate('c'), 'isCustom' => false, )));
                $valid = $this->validate_scheme_complete($clean);

                if (is_wp_error($valid)) {
                    return new WP_REST_Response(array('success' => false, 'code' => $valid->get_error_code(), 'message' => $valid->get_error_message(), ), 400);
                } $new_schemes[] = $clean;
            } $new_active_id = $new_schemes[0]['id'];
            $data = array('schemes' => $new_schemes, 'activeSchemeId' => $new_active_id, 'updatedAt' => current_time('c'), 'compiledCss' => $new_schemes[0]['compiledCss'], );
            update_option(self::OPTION_KEY, $data, false);

            return new WP_REST_Response(array('success' => true, 'data' => array('schemes' => $new_schemes, 'activeSchemeId' => $new_active_id, ), ), 200);
        } catch (PufferGo_API_Exception $e) {
            puffergo_log('[DesignSystem Generate] API Exception: ' . $e->getMessage());

            return new WP_REST_Response($e->toArray(), $e->getCode());
        } catch (Exception $e) {
            puffergo_log('[DesignSystem Generate] Error: ' . $e->getMessage());

            return new WP_REST_Response(array('success' => false, 'message' => $e->getMessage(), ), 500);
        }
    }

    public function rest_get($request)
    {
        $raw = get_option(self::OPTION_KEY, null);
        $schemes = isset($raw['schemes']) ? $raw['schemes'] : array();
        $data = is_array($raw) ? array('schemes' => $schemes, 'activeSchemeId' => isset($raw['activeSchemeId']) ? $raw['activeSchemeId'] : '', 'updatedAt' => isset($raw['updatedAt']) ? $raw['updatedAt'] : '', ) : array('schemes' => array(), 'activeSchemeId' => '', 'updatedAt' => '');

        return new WP_REST_Response(array('success' => true, 'data' => $data, ), 200);
    }

    public function rest_save($request)
    {
        $params = $request->get_json_params();
        $schemes = isset($params['schemes']) && is_array($params['schemes']) ? $params['schemes'] : array();
        $active_id = isset($params['activeSchemeId']) ? sanitize_text_field(wp_unslash($params['activeSchemeId'])) : '';

        if ('' !== $active_id && empty($schemes)) {
            return new WP_REST_Response(array('success' => false, 'code' => 'puffergo_active_without_schemes', 'message' => esc_html__('Cannot set activeSchemeId without at least one scheme.', 'puffergo'), ), 400);
        } $sanitized_schemes = array();
        $seen_ids = array();

        foreach ($schemes as $scheme) {
            $clean = $this->sanitize_scheme($scheme);

            if (isset($seen_ids[$clean['id']])) {
                return new WP_REST_Response(array('success' => false, 'code' => 'puffergo_duplicate_scheme_id', 'message' => esc_html__('Duplicate scheme id in payload.', 'puffergo'), ), 400);
            } $seen_ids[$clean['id']] = true;
            $valid = $this->validate_scheme_complete($clean);

            if (is_wp_error($valid)) {
                return new WP_REST_Response(array('success' => false, 'code' => $valid->get_error_code(), 'message' => $valid->get_error_message(), ), 400);
            } $sanitized_schemes[] = $clean;
        }

if ('' !== $active_id && ! empty($sanitized_schemes)) {
            $valid_active = false;

            foreach ($sanitized_schemes as $s) {
                if (isset($s['id']) && $s['id'] === $active_id) {
                    $valid_active = true;
                    break;
                }
            }

if (! $valid_active) {
                return new WP_REST_Response(array('success' => false, 'code' => 'puffergo_active_scheme_not_found', 'message' => esc_html__('activeSchemeId must match one of the saved schemes.', 'puffergo'), ), 400);
            }
        } $data = array('schemes' => $sanitized_schemes, 'activeSchemeId' => $active_id, 'overrides' => self::get_overrides(), 'updatedAt' => current_time('c'), );

        foreach ($sanitized_schemes as $scheme) {
            if (isset($scheme['id']) && $scheme['id'] === $active_id) {
                $data['compiledCss'] = $scheme['compiledCss'];
                break;
            }
        } update_option(self::OPTION_KEY, $data, false);

        return new WP_REST_Response(array('success' => true, 'data' => $data, ), 200);
    }

    private function validate_scheme_complete(array $scheme)
    {
        $min_css = 80;

        if (empty($scheme['id']) || ! is_string($scheme['id'])) {
            return new WP_Error('puffergo_scheme_invalid_id', esc_html__('Each design scheme must have a non-empty id.', 'puffergo'));
        } $css = isset($scheme['compiledCss']) ? $scheme['compiledCss'] : '';

        if (! is_string($css) || strlen(trim($css)) < $min_css) {
            return new WP_Error('puffergo_scheme_missing_compiled_css', esc_html__('Design scheme must include compiled CSS from the server (compiledCss).', 'puffergo'));
        }

if (false === strpos($css, ':root')) {
            return new WP_Error('puffergo_scheme_compiled_css_malformed', esc_html__('compiledCss must contain a :root block.', 'puffergo'));
        } $t = isset($scheme['tokens']) && is_array($scheme['tokens']) ? $scheme['tokens'] : array();

        foreach (array('primaryColor', 'secondaryColor', 'baseColor', 'borderRadius', 'fontHeading', 'fontBody') as $key) {
            if (! isset($t[$key]) || '' === trim((string) $t[$key])) {
                return new WP_Error('puffergo_scheme_incomplete_tokens', esc_html__('Design scheme tokens are incomplete.', 'puffergo'));
            }
        }

foreach (array('primaryColor', 'secondaryColor', 'baseColor') as $hex_key) {
            if (! sanitize_hex_color($t[$hex_key])) {
                return new WP_Error('puffergo_scheme_invalid_token_color', esc_html__('Token colors must be valid hex values.', 'puffergo'));
            }
        }

return true;
    }

    private function sanitize_scheme($scheme)
    {
        $allowed_radii = array('0px', '2px', '4px', '6px', '8px', '12px', '16px', '18px', '9999px');
        $allowed_fonts = array_merge(array_keys(PufferGo_Theme_Bridge::GOOGLE_FONTS_MAP), array('sans-serif', 'serif', 'monospace', 'system-ui', 'Arial', 'Helvetica', 'Georgia', 'Times New Roman'));
        $t = isset($scheme['tokens']) && is_array($scheme['tokens']) ? $scheme['tokens'] : array();
        $primary = sanitize_hex_color($t['primaryColor'] ?? '') ?: '#3b82f6';
        $secondary = sanitize_hex_color($t['secondaryColor'] ?? '') ?: '#f59e0b';
        $base = sanitize_hex_color($t['baseColor'] ?? '') ?: '#ffffff';
        $raw_radius = isset($t['borderRadius']) ? sanitize_text_field($t['borderRadius']) : '8px';
        $radius = in_array($raw_radius, $allowed_radii, true) ? $raw_radius : '8px';
        $raw_heading = isset($t['fontHeading']) ? sanitize_text_field($t['fontHeading']) : 'sans-serif';
        $raw_body = isset($t['fontBody']) ? sanitize_text_field($t['fontBody']) : 'sans-serif';
        $font_heading = in_array($raw_heading, $allowed_fonts, true) ? $raw_heading : 'sans-serif';
        $font_body = in_array($raw_body, $allowed_fonts, true) ? $raw_body : 'sans-serif';

        return array('id' => sanitize_text_field($scheme['id'] ?? ''), 'name' => sanitize_text_field($scheme['name'] ?? ''), 'rationale' => sanitize_textarea_field($scheme['rationale'] ?? ''), 'generatedAt' => sanitize_text_field($scheme['generatedAt'] ?? ''), 'isCustom' => (bool) ($scheme['isCustom'] ?? false), 'compiledCss' => isset($scheme['compiledCss']) ? $scheme['compiledCss'] : '', 'tokens' => array('primaryColor' => $primary, 'secondaryColor' => $secondary, 'baseColor' => $base, 'borderRadius' => $radius, 'fontHeading' => $font_heading, 'fontBody' => $font_body, ), );
    }

    public static function get_active_tokens()
    {
        $data = get_option(self::OPTION_KEY, null);

        if (! $data || ! is_array($data) || empty($data['schemes']) || ! is_array($data['schemes'])) {
            return null;
        } $active_id = isset($data['activeSchemeId']) ? (string) $data['activeSchemeId'] : '';

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

foreach ($data['schemes'] as $scheme) {
            if (isset($scheme['id']) && $scheme['id'] === $active_id) {
                return isset($scheme['tokens']) ? $scheme['tokens'] : null;
            }
        }

return null;
    }

    public static function get_compiled_css()
    {
        $data = get_option(self::OPTION_KEY, null);

        if (! $data || ! is_array($data)) {
            return null;
        } $active_id = isset($data['activeSchemeId']) ? (string) $data['activeSchemeId'] : '';

        if ('' !== $active_id && ! empty($data['schemes'])) {
            foreach ($data['schemes'] as $scheme) {
                if (isset($scheme['id']) && $scheme['id'] === $active_id) {
                    $compiled = isset($scheme['compiledCss']) ? $scheme['compiledCss'] : '';

                    if (! empty($compiled)) {
                        return $compiled;
                    } break;
                }
            }
        }

return isset($data['compiledCss']) ? $data['compiledCss'] : null;
    }

    public function rest_get_overrides()
    {
        return new WP_REST_Response(array('success' => true, 'data' => array('overrides' => self::get_overrides(), 'schema' => self::OVERRIDES, ), ), 200);
    }

    public function rest_save_overrides($request)
    {
        $params = $request->get_json_params();
        $input = isset($params['overrides']) && is_array($params['overrides']) ? $params['overrides'] : array();
        $data = get_option(self::OPTION_KEY, array());

        if (! is_array($data)) {
            $data = array();
        } $data['overrides'] = self::sanitize_overrides($input);
        update_option(self::OPTION_KEY, $data, false);

        return new WP_REST_Response(array('success' => true, 'data' => array('overrides' => $data['overrides']), ), 200);
    }

    private static function sanitize_overrides($input)
    {
        $clean = array();

        foreach (self::OVERRIDES as $key => $item) {
            if (isset($input[ $key ]) && isset($item['options'][ $input[ $key ] ])) {
                $clean[ $key ] = $input[ $key ];
            }
        }

return $clean;
    }

    public static function get_overrides()
    {
        $data = get_option(self::OPTION_KEY, null);
        $raw = (is_array($data) && isset($data['overrides']) && is_array($data['overrides'])) ? $data['overrides'] : array();

        return self::sanitize_overrides($raw);
    }

    public static function get_override_css()
    {
        $css = '';

        foreach (self::get_overrides() as $key => $value) {
            foreach (self::OVERRIDES[ $key ]['options'][ $value ]['vars'] as $var => $val) {
                $css .= "\n    {$var}: {$val};";
            }
        }

return $css;
    }
} new PufferGo_Design_System();
