<?php

namespace Miruni\RestApi;

use WP_Error;
use WP_REST_Response;

if (!defined('ABSPATH'))
    exit; // Exit if accessed directly

// Load the schema extractor (global class)
require_once __DIR__ . '/../elementor/schema-extractor.php';

class Miruni_Elementor_Schema_API extends Miruni_BaseAPI
{
    public static string $namespace = 'miruni/v1';
    public static string $route = '/elementor-schema/';

    /**
     * Get the REST URL for the Elementor schema endpoint.
     * @return string
     */
    public static function get_rest_url(int $page_id): string
    {
        return self::_get_rest_url(['page_id' => $page_id]);
    }

    public static function setup(): void
    {
        add_action('rest_api_init', function () {
            register_rest_route(self::$namespace, self::$route, [
                'methods' => 'GET',
                'callback' => [__CLASS__, 'get_elementor_schema'],
                'permission_callback' => [__CLASS__, 'snippet_secret_required_permission_callback'],
                'args' => [
                    'page_id' => [
                        'required' => false,
                        'validate_callback' => function ($param) {
                            return is_numeric($param) && (int) $param >= 0;
                        },
                        'sanitize_callback' => 'absint',
                        'description' => 'Optional WordPress post/page ID to scope extraction and improve control registration.'
                    ],
                    'format' => [
                        'required' => false,
                        'validate_callback' => function ($param) {
                            return in_array($param, ['json', 'yaml', 'markdown']);
                        },
                        'sanitize_callback' => 'sanitize_text_field',
                    ],
                    // This endpoint now only supports extracting schema for a specific
                    // type (element or widget) and a comma-separated list of fields.
                    'type' => [
                        'required' => true,
                        'validate_callback' => function ($param) {
                            return is_string($param) && strlen($param) > 0;
                        },
                        'sanitize_callback' => 'sanitize_text_field',
                    ],
                    'fields' => [
                        'required' => false,
                        'validate_callback' => function ($param) {
                            return is_string($param) || is_array($param) || is_null($param);
                        },
                        'sanitize_callback' => 'sanitize_text_field',
                    ],
                ],
            ]);
        });
    }

    /**
     * Return the extracted Elementor schema.
     * @param \WP_REST_Request<array<mixed>> $request
     * @return WP_Error|WP_REST_Response
     */
    public static function get_elementor_schema(\WP_REST_Request $request): WP_Error|WP_REST_Response
    {
        // Ensure Elementor is available
        if (!class_exists('\Elementor\Plugin')) {
            error_log('Miruni: Elementor class not found when calling elementor-schema endpoint');
            return new WP_Error('elementor_missing', 'Elementor plugin not active or not available.', ['status' => 500]);
        }

        // Ensure the plugin instance is initialized
        // @phpstan-ignore-next-line
        if (!isset(\Elementor\Plugin::$instance) || !\Elementor\Plugin::$instance) {
            error_log('Miruni: Elementor plugin class exists but instance is not initialized');
            return new WP_Error('elementor_not_ready', 'Elementor plugin loaded but not initialized yet. Try again after init.', ['status' => 500]);
        }

        try {
            // Instantiate extractor
            $extractor = new \ElementorSchemaExtractor();

            // Only support targeted extraction: ?type=widgets/heading or ?type=widget/elementskit-heading
            $type = $request->get_param('type');
            $fields = $request->get_param('fields') ?? null;
            $page_id = $request->get_param('page_id');
            $page_id = is_numeric($page_id) ? (int) $page_id : null;

            // Ensure Elementor editor mode so group controls (e.g., typography) are registered
            try {
                /** @phpstan-ignore-next-line */
                \Elementor\Plugin::$instance->editor->set_edit_mode(true);

                // Touch common group control classes to ensure they are autoloaded
                if (!class_exists('\\Elementor\\Group_Control_Typography')) {
                    // Trigger autoload if available
                    @class_exists('\\Elementor\\Group_Control_Typography');
                }
            } catch (\Throwable $e) {
                // Non-fatal; continue
                error_log('Miruni: Failed to toggle Elementor edit mode for schema extraction - ' . $e->getMessage());
            }

            if (empty($type)) {
                return new WP_Error('missing_type', 'The "type" parameter is required. Provide a type like "widget/heading" or "element/section".', ['status' => 400]);
            }

            // Normalize fields: array or comma-separated string
            if (is_array($fields)) {
                $fields_param = $fields;
            } elseif (is_string($fields) && strpos($fields, ',') !== false) {
                $fields_param = array_map('trim', explode(',', $fields));
            } elseif (is_string($fields) && strlen($fields) > 0) {
                $fields_param = [$fields];
            } else {
                $fields_param = [];
            }


            // Pass page_id to allow scoping and better control discovery; keep kind default and
            // rely on path-style $type (e.g., widget/heading) to set the correct kind internally
            $raw_or_formatted = $extractor->extract_schema_for_fields($type, $fields_param, 'element', $page_id);
            if (is_string($raw_or_formatted)) {
                $schemas = json_decode($raw_or_formatted, true);
                if (json_last_error() !== JSON_ERROR_NONE) {
                    error_log('Miruni: JSON decode error in elementor schema (targeted): ' . json_last_error_msg());
                    $schemas = $raw_or_formatted;
                }
            } else {
                $schemas = $raw_or_formatted;
            }
        } catch (\Throwable $e) {
            error_log('Miruni: elementor schema extraction failed: ' . $e->getMessage());
            return new WP_Error('schema_extraction_failed', $e->getMessage(), ['status' => 500]);
        }

        $response = [
            'schema' => $schemas,
        ];

        return new WP_REST_Response($response, 200);
    }
}
