<?php
/**
 * SCHEMAFY REST API Class
 * 
 * Handles all REST API endpoints for the Custom Schema by SCHEMAFY plugin
 * 
 * @package CustomSchemaSchemafy
 * @since 1.1.85
 * @author SCHEMAFY Team
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Class SCHEMAFY_REST_API
 * 
 * Manages all REST API endpoints for schema operations
 */
class SCHEMAFY_REST_API {
    
    /**
     * Validator instance
     * 
     * @var SCHEMAFY_Validator
     */
    private $validator;
    
    /**
     * Database instance
     * 
     * @var SCHEMAFY_Database
     */
    private $database;
    
    /**
     * API namespace
     * 
     * @var string
     */
    private $namespace = 'schemafy/v1';
    
    /**
     * Constructor
     * 
     * @param SCHEMAFY_Validator $validator Validator instance
     * @param SCHEMAFY_Database $database Database instance
     */
    public function __construct($validator, $database) {
        $this->validator = $validator;
        $this->database = $database;
    }
    
    /**
     * Register REST API routes
     * Called by WordPress rest_api_init hook
     * 
     * @return void
     */
    public function register_routes() {
        // List and create schemas
        register_rest_route($this->namespace, '/schemas', array(
            array(
                'methods' => 'GET',
                'callback' => array($this, 'get_schemas'),
                'permission_callback' => array($this, 'permission_check')
            ),
            array(
                'methods' => 'POST',
                'callback' => array($this, 'create_schema'),
                'permission_callback' => array($this, 'permission_check')
            )
        ));
        
        // Get, update, and delete specific schema
        register_rest_route($this->namespace, '/schemas/(?P<id>\d+)', array(
            array(
                'methods' => 'GET',
                'callback' => array($this, 'get_schema'),
                'permission_callback' => array($this, 'permission_check')
            ),
            array(
                'methods' => 'PUT',
                'callback' => array($this, 'update_schema'),
                'permission_callback' => array($this, 'permission_check')
            ),
            array(
                'methods' => 'DELETE',
                'callback' => array($this, 'delete_schema'),
                'permission_callback' => array($this, 'permission_check')
            )
        ));
        
        // Toggle schema active/inactive status
        register_rest_route($this->namespace, '/schemas/(?P<id>\d+)/toggle', array(
            'methods' => 'POST',
            'callback' => array($this, 'toggle_schema'),
            'permission_callback' => array($this, 'permission_check')
        ));
        
        // Bulk apply schemas to multiple URLs
        register_rest_route($this->namespace, '/schemas/bulk-apply', array(
            'methods' => 'POST',
            'callback' => array($this, 'bulk_apply_schemas'),
            'permission_callback' => array($this, 'permission_check')
        ));

        // SEO Analysis endpoint
        register_rest_route($this->namespace, '/analyze-seo', array(
            'methods' => 'POST',
            'callback' => array($this, 'analyze_seo'),
            'permission_callback' => array($this, 'edit_posts_check'),
            'args' => array(
                'post_id' => array(
                    'required' => true,
                    'type' => 'integer',
                    'sanitize_callback' => 'absint'
                ),
                'focus_keyword' => array(
                    'type' => 'string',
                    'default' => '',
                    'sanitize_callback' => 'sanitize_text_field'
                ),
                'title' => array(
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_text_field'
                ),
                'description' => array(
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_textarea_field'
                ),
                'content' => array(
                    'type' => 'string'
                )
            )
        ));

        // Get schemas by URL (for editor integration)
        register_rest_route($this->namespace, '/schemas-by-url', array(
            'methods' => 'GET',
            'callback' => array($this, 'get_schemas_by_url'),
            'permission_callback' => array($this, 'can_edit_url_schema'),
            'args' => array(
                'url' => array(
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'esc_url_raw'
                )
            )
        ));

        // Export all schemas as JSON
        register_rest_route($this->namespace, '/schemas/export', array(
            'methods' => 'GET',
            'callback' => array($this, 'export_schemas'),
            'permission_callback' => array($this, 'permission_check')
        ));

        // Import schemas from JSON
        register_rest_route($this->namespace, '/schemas/import', array(
            'methods' => 'POST',
            'callback' => array($this, 'import_schemas'),
            'permission_callback' => array($this, 'permission_check')
        ));

        // Auto-detect schema recommendations for a post
        register_rest_route($this->namespace, '/auto-detect/(?P<post_id>\d+)', array(
            'methods' => 'GET',
            'callback' => array($this, 'auto_detect_for_post'),
            'permission_callback' => array($this, 'edit_posts_check'),
            'args' => array(
                'post_id' => array(
                    'required' => true,
                    'type' => 'integer',
                    'sanitize_callback' => 'absint'
                )
            )
        ));
    }
    
    /**
     * Permission check for REST API endpoints
     * 
     * @param WP_REST_Request $request Request object
     * @return bool True if user has permission, false otherwise
     */
    public function permission_check($request) {
        return $this->validator->validate_user_capability('manage_options');
    }
    
    /**
     * GET /schemas - Get all schemas with pagination and filters
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response or error
     */
    public function get_schemas($request) {
        // Get and sanitize query parameters
        $page = max(1, intval($request->get_param('page') ?? 1));
        $per_page = min(100, max(1, intval($request->get_param('per_page') ?? 20)));
        $url_filter = $request->get_param('url');
        $type_filter = $request->get_param('schema_type');
        $search_filter = $request->get_param('search');
        
        // Sanitize pagination
        $pagination = $this->validator->sanitize_pagination($page, $per_page);
        
        // Validate schema_type if provided
        if ($type_filter !== null) {
            if (!$this->validator->is_valid_schema_type($type_filter)) {
                return new WP_Error('invalid_type', __('Invalid schema type', 'schemafy'), array('status' => 400));
            }
            $type_filter = sanitize_text_field($type_filter);
        }
        
        // Sanitize URL if provided
        if ($url_filter !== null) {
            $url_filter = $this->validator->sanitize_url($url_filter);
        }
        
        // Sanitize search if provided
        if ($search_filter !== null) {
            $search_filter = $this->validator->sanitize_search_query($search_filter);
        }
        
        // Get schemas from database
        $result = $this->database->get_schemas(array(
            'page' => $pagination['page'],
            'per_page' => $pagination['per_page'],
            'url' => $url_filter,
            'schema_type' => $type_filter,
            'search' => $search_filter
        ));
        
        // Convert objects to arrays for REST response
        $items = array();
        foreach ($result['items'] as $item) {
            $items[] = (array) $item;
        }
        
        // Create response with pagination headers
        $response = new WP_REST_Response($items);
        
        $response->header('X-WP-Total', $result['total']);
        $response->header('X-WP-TotalPages', $result['pages']);
        $response->header('X-WP-Page', $result['current_page']);
        $response->header('X-WP-Per-Page', $result['per_page']);
        
        // Build Link headers for pagination
        $links = array();
        
        // Self link
        $self_params = array_filter(array(
            'page' => $result['current_page'],
            'per_page' => $result['per_page'],
            'schema_type' => $type_filter,
            'url' => $url_filter,
            'search' => $search_filter
        ));
        $self_url = rest_url($this->namespace . '/schemas') . '?' . http_build_query($self_params, '', '&', PHP_QUERY_RFC3986);
        $links[] = '<' . $self_url . '>; rel="self"';
        
        // First page link
        if ($result['current_page'] > 1) {
            $first_params = array_filter(array(
                'page' => 1,
                'per_page' => $result['per_page'],
                'schema_type' => $type_filter,
                'url' => $url_filter,
                'search' => $search_filter
            ));
            $first_url = rest_url($this->namespace . '/schemas') . '?' . http_build_query($first_params, '', '&', PHP_QUERY_RFC3986);
            $links[] = '<' . $first_url . '>; rel="first"';
        }
        
        // Previous page link
        if ($result['current_page'] > 1) {
            $prev_params = array_filter(array(
                'page' => $result['current_page'] - 1,
                'per_page' => $result['per_page'],
                'schema_type' => $type_filter,
                'url' => $url_filter,
                'search' => $search_filter
            ));
            $prev_url = rest_url($this->namespace . '/schemas') . '?' . http_build_query($prev_params, '', '&', PHP_QUERY_RFC3986);
            $links[] = '<' . $prev_url . '>; rel="prev"';
        }
        
        // Next page link
        if ($result['current_page'] < $result['pages']) {
            $next_params = array_filter(array(
                'page' => $result['current_page'] + 1,
                'per_page' => $result['per_page'],
                'schema_type' => $type_filter,
                'url' => $url_filter,
                'search' => $search_filter
            ));
            $next_url = rest_url($this->namespace . '/schemas') . '?' . http_build_query($next_params, '', '&', PHP_QUERY_RFC3986);
            $links[] = '<' . $next_url . '>; rel="next"';
        }
        
        // Last page link
        if ($result['current_page'] < $result['pages'] && $result['pages'] > 1) {
            $last_params = array_filter(array(
                'page' => $result['pages'],
                'per_page' => $result['per_page'],
                'schema_type' => $type_filter,
                'url' => $url_filter,
                'search' => $search_filter
            ));
            $last_url = rest_url($this->namespace . '/schemas') . '?' . http_build_query($last_params, '', '&', PHP_QUERY_RFC3986);
            $links[] = '<' . $last_url . '>; rel="last"';
        }
        
        // Set Link header if we have links
        if (!empty($links)) {
            $response->header('Link', implode(', ', $links));
        }
        
        return $response;
    }
    
    /**
     * GET /schemas/{id} - Get single schema
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response or error
     */
    public function get_schema($request) {
        $id = $this->validator->sanitize_id($request['id']);
        
        $schema = $this->database->get_schema($id);
        
        if (!$schema) {
            return new WP_Error('not_found', __('Schema not found', 'schemafy'), array('status' => 404));
        }
        
        return rest_ensure_response((array) $schema);
    }
    
    /**
     * POST /schemas - Create new schema
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response or error
     */
    public function create_schema($request) {
        $params = $request->get_json_params();
        
        // Sanitize data
        $data = array(
            'url' => $this->validator->sanitize_url($params['url'] ?? ''),
            'schema_type' => sanitize_text_field($params['schema_type'] ?? 'WebPage'),
            'schema_name' => $this->validator->sanitize_schema_name($params['schema_name'] ?? __('Schema without name', 'schemafy')),
            'schema_data' => wp_unslash($params['schema_data'] ?? ''),
            'meta_title' => isset($params['meta_title']) ? sanitize_text_field($params['meta_title']) : '',
            'meta_description' => isset($params['meta_description']) ? sanitize_textarea_field($params['meta_description']) : '',
            'is_active' => isset($params['is_active']) ? intval($params['is_active']) : 1
        );
        
        // Canonize URL to HTTPS
        $data['url'] = $this->canonize_url_https($data['url']);
        
        // Validate data
        $validation = $this->validator->validate_schema_create_data($data);
        if (is_wp_error($validation)) {
            return $validation;
        }
        
        // Create schema
        $id = $this->database->create_schema($data);
        
        if ($id === false) {
            return new WP_Error('db_error', __('Error saving schema', 'schemafy'), array('status' => 500));
        }
        
        SCHEMAFY_Schema_Injector::clear_all_schema_cache();
        return rest_ensure_response(array('id' => $id, 'success' => true));
    }

    /**
     * PUT /schemas/{id} - Update existing schema
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response or error
     */
    public function update_schema($request) {
        $id = $this->validator->sanitize_id($request['id']);
        $params = $request->get_json_params();
        
        // Check if schema exists
        if (!$this->database->schema_exists($id)) {
            return new WP_Error('not_found', __('Schema not found', 'schemafy'), array('status' => 404));
        }
        
        // Sanitize data
        $data = array(
            'url' => $this->validator->sanitize_url($params['url'] ?? ''),
            'schema_type' => sanitize_text_field($params['schema_type'] ?? 'WebPage'),
            'schema_name' => $this->validator->sanitize_schema_name($params['schema_name'] ?? __('Schema without name', 'schemafy')),
            'schema_data' => wp_unslash($params['schema_data'] ?? ''),
            'meta_title' => isset($params['meta_title']) ? sanitize_text_field($params['meta_title']) : '',
            'meta_description' => isset($params['meta_description']) ? sanitize_textarea_field($params['meta_description']) : ''
        );
        
        // Canonize URL to HTTPS
        $data['url'] = $this->canonize_url_https($data['url']);
        
        // Validate data
        $validation = $this->validator->validate_schema_update_data($data, false);
        if (is_wp_error($validation)) {
            return $validation;
        }
        
        // Update schema
        $result = $this->database->update_schema($id, $data);
        
        if ($result === false) {
            return new WP_Error('db_error', __('Error updating schema', 'schemafy'), array('status' => 500));
        }
        
        SCHEMAFY_Schema_Injector::clear_all_schema_cache();
        return rest_ensure_response(array('success' => true));
    }

    /**
     * DELETE /schemas/{id} - Delete schema
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response or error
     */
    public function delete_schema($request) {
        $id = $this->validator->sanitize_id($request['id']);
        
        // Check if schema exists
        if (!$this->database->schema_exists($id)) {
            return new WP_Error('not_found', __('Schema not found', 'schemafy'), array('status' => 404));
        }
        
        // Delete schema
        $result = $this->database->delete_schema($id);
        
        if ($result === false) {
            return new WP_Error('db_error', __('Error deleting schema', 'schemafy'), array('status' => 500));
        }
        
        SCHEMAFY_Schema_Injector::clear_all_schema_cache();
        return rest_ensure_response(array('success' => true));
    }

    /**
     * POST /schemas/{id}/toggle - Toggle schema active status
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response or error
     */
    public function toggle_schema($request) {
        $id = $this->validator->sanitize_id($request['id']);
        
        // Check if schema exists
        if (!$this->database->schema_exists($id)) {
            return new WP_Error('not_found', __('Schema not found', 'schemafy'), array('status' => 404));
        }
        
        // Toggle status
        $new_status = $this->database->toggle_schema($id);
        
        if ($new_status === false) {
            return new WP_Error('db_error', __('Error updating status', 'schemafy'), array('status' => 500));
        }
        
        SCHEMAFY_Schema_Injector::clear_all_schema_cache();
        return rest_ensure_response(array('is_active' => $new_status));
    }

    /**
     * POST /schemas/bulk-apply - Bulk apply schema to multiple URLs
     * 
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response or error
     */
    public function bulk_apply_schemas($request) {
        $params = $request->get_json_params();
        
        // Validate bulk data
        $validation = $this->validator->validate_bulk_apply_data($params);
        if (is_wp_error($validation)) {
            return $validation;
        }
        
        // Prepare base data
        $schema_name = $this->validator->sanitize_schema_name($params['schema_name'] ?? __('Bulk Schema', 'schemafy'));
        $schema_type = sanitize_text_field($params['schema_type'] ?? 'WebPage');
        $schema_data = wp_unslash($params['schema_data'] ?? '');
        $meta_title = isset($params['meta_title']) ? sanitize_text_field($params['meta_title']) : '';
        $meta_description = isset($params['meta_description']) ? sanitize_textarea_field($params['meta_description']) : '';
        
        // Build schemas array
        $schemas = array();
        foreach ($params['urls'] as $url) {
            $url = $this->validator->sanitize_url($url);
            $url = $this->canonize_url_https($url);
            
            $schemas[] = array(
                'url' => $url,
                'schema_name' => $schema_name,
                'schema_data' => $schema_data,
                'schema_type' => $schema_type,
                'meta_title' => $meta_title,
                'meta_description' => $meta_description,
                'is_active' => 1
            );
        }
        
        // Bulk create
        $results = $this->database->bulk_create_schemas($schemas);
        
        return rest_ensure_response(array(
            'success' => $results['success'],
            'failed' => $results['failed'],
            'errors' => $results['errors']
        ));
    }
    
    /**
     * Permission check for edit posts capability
     *
     * @param WP_REST_Request $request Request object
     * @return bool True if user can edit posts
     */
    public function edit_posts_check($request) {
        return current_user_can('edit_posts');
    }

    /**
     * Permission check for URL-scoped schema reads.
     *
     * Verifies the caller can edit the SPECIFIC post the URL maps to, instead
     * of granting any edit_posts user access to every URL's stored schema.
     *
     * @param WP_REST_Request $request Request object
     * @return bool
     */
    public function can_edit_url_schema($request) {
        if (current_user_can('manage_options')) {
            return true;
        }

        $url     = esc_url_raw((string) $request->get_param('url'));
        $post_id = $url ? url_to_postid($url) : 0;

        if ($post_id > 0) {
            return current_user_can('edit_post', $post_id);
        }

        // URL not tied to a local post (e.g. a custom URL): require the broader
        // capability rather than leaking arbitrary stored data.
        return current_user_can('edit_others_posts');
    }

    /**
     * POST /analyze-seo - Analyze post SEO
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error Response or error
     */
    public function analyze_seo($request) {
        $post_id = $request->get_param('post_id');
        $focus_keyword = $request->get_param('focus_keyword');

        // Check if post exists and user can edit it
        $post = get_post($post_id);
        if (!$post) {
            return new WP_Error('not_found', __('Post not found', 'schemafy'), array('status' => 404));
        }

        if (!current_user_can('edit_post', $post_id)) {
            return new WP_Error('forbidden', __('You cannot edit this post', 'schemafy'), array('status' => 403));
        }

        // Get override data for live editing
        $override_data = array();
        if ($request->get_param('title') !== null) {
            $override_data['title'] = $request->get_param('title');
        }
        if ($request->get_param('description') !== null) {
            $override_data['description'] = $request->get_param('description');
        }
        if ($request->get_param('content') !== null) {
            $override_data['content'] = wp_kses_post($request->get_param('content'));
        }

        // Create analyzer instance
        $analyzer = new SCHEMAFY_SEO_Analyzer($this->database);
        $result = $analyzer->analyze_post($post_id, $focus_keyword, $override_data);

        return rest_ensure_response($result);
    }

    /**
     * GET /schemas-by-url - Get schemas for a specific URL
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response Response
     */
    public function get_schemas_by_url($request) {
        $original_url = $request->get_param('url');

        // Canonize URL
        $url = $this->canonize_url_https($original_url);

        // Try multiple URL variations for better matching
        $url_variations = $this->get_url_variations($url);
        $schemas = array();
        $matched_url = '';
        $match_type = 'none';

        // First try exact matching with variations
        foreach ($url_variations as $url_variant) {
            $found = $this->database->get_schemas_by_url($url_variant, false);
            if (!empty($found)) {
                $schemas = $found;
                $matched_url = $url_variant;
                $match_type = 'exact';
                break;
            }
        }

        // If no exact match, try flexible LIKE matching
        if (empty($schemas)) {
            $found = $this->database->get_schemas_by_url_flexible($url, false);
            if (!empty($found)) {
                $schemas = $found;
                $matched_url = $url;
                $match_type = 'flexible';
            }
        }

        // Ensure array format
        $items = array();
        if (is_array($schemas)) {
            foreach ($schemas as $schema) {
                $items[] = (array) $schema;
            }
        }

        // Build response with debug info
        $response = array(
            'url' => $url,
            'schemas' => $items,
            'count' => count($items)
        );

        // Add debug info only if WP_DEBUG is enabled
        if (defined('WP_DEBUG') && WP_DEBUG) {
            $response['debug'] = array(
                'original_url' => $original_url,
                'canonized_url' => $url,
                'variations_tried' => $url_variations,
                'matched_url' => $matched_url,
                'match_type' => $match_type
            );
        }

        return rest_ensure_response($response);
    }

    /**
     * Get URL variations for matching (with/without trailing slash, www, protocol)
     *
     * @param string $url Original URL
     * @return array Array of URL variations to try
     */
    private function get_url_variations($url) {
        $variations = array();
        $base_urls = array($url);

        // Parse the URL to manipulate parts
        $parsed = wp_parse_url($url);
        if (!$parsed || !isset($parsed['host'])) {
            return array($url);
        }

        $host = $parsed['host'];
        $path = isset($parsed['path']) ? $parsed['path'] : '';
        $query = isset($parsed['query']) ? '?' . $parsed['query'] : '';

        // Generate host variants (with/without www)
        $hosts = array($host);
        if (strpos($host, 'www.') === 0) {
            $hosts[] = substr($host, 4); // Remove www.
        } else {
            $hosts[] = 'www.' . $host; // Add www.
        }

        // Generate protocol variants
        $protocols = array('https://', 'http://');

        // Generate path variants (with/without trailing slash)
        $paths = array($path . $query);
        if (substr($path, -1) === '/') {
            $paths[] = rtrim($path, '/') . $query;
        } else {
            $paths[] = $path . '/' . $query;
        }

        // Combine all variations
        foreach ($protocols as $protocol) {
            foreach ($hosts as $h) {
                foreach ($paths as $p) {
                    $variations[] = $protocol . $h . $p;
                }
            }
        }

        // Remove duplicates and return
        return array_unique($variations);
    }

    /**
     * GET /schemas/export — Download all schemas as a JSON file
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public function export_schemas($request) {
        global $wpdb;
        $table   = $wpdb->prefix . 'schemafy_custom_schemas';
        $schemas = $wpdb->get_results( "SELECT * FROM $table ORDER BY id ASC", ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- $table_name comes from $wpdb->prefix (trusted), identifiers cannot be placeholders, and this is a custom table with no object cache

        $payload = array(
            'version'     => defined('SCHEMAFY_VERSION') ? SCHEMAFY_VERSION : '0',
            'exported_at' => gmdate('c'),
            'site_url'    => home_url(),
            'count'       => count($schemas),
            'schemas'     => $schemas ?: array(),
        );

        $response = new WP_REST_Response($payload, 200);
        $filename = 'schemafy-export-' . gmdate('Y-m-d') . '.json';
        $response->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
        return $response;
    }

    /**
     * POST /schemas/import — Bulk-create schemas from exported JSON
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response|WP_Error
     */
    public function import_schemas($request) {
        $params = $request->get_json_params();

        if ( empty($params['schemas']) || ! is_array($params['schemas']) ) {
            return new WP_Error( 'invalid_data', __('No schemas found in import data', 'schemafy'), array('status' => 400) );
        }

        $imported = 0;
        $skipped  = 0;
        $errors   = array();

        foreach ( $params['schemas'] as $row ) {
            $url  = $this->validator->sanitize_url( $row['url'] ?? '' );
            $data = $row['schema_data'] ?? '';

            if ( empty($url) || empty($data) ) {
                $skipped++;
                continue;
            }

            $insert = array(
                'url'              => $this->canonize_url_https($url),
                'schema_type'      => sanitize_text_field( $row['schema_type']      ?? 'WebPage' ),
                'schema_name'      => $this->validator->sanitize_schema_name( $row['schema_name'] ?? __('Imported Schema', 'schemafy') ),
                'schema_data'      => wp_unslash( $data ),
                'meta_title'       => sanitize_text_field( $row['meta_title']        ?? '' ),
                'meta_description' => sanitize_textarea_field( $row['meta_description'] ?? '' ),
                'is_active'        => isset($row['is_active']) ? intval($row['is_active']) : 1,
            );

            $id = $this->database->create_schema($insert);
            if ($id) {
                $imported++;
            } else {
                $errors[] = $url;
            }
        }

        SCHEMAFY_Schema_Injector::clear_all_schema_cache();

        return rest_ensure_response(array(
            'imported' => $imported,
            'skipped'  => $skipped,
            'errors'   => $errors,
        ));
    }

    /**
     * GET /auto-detect/{post_id} — Return auto-generator recommendations for a post
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response|WP_Error
     */
    public function auto_detect_for_post($request) {
        $post_id = absint( $request['post_id'] );
        $post    = get_post($post_id);

        if ( ! $post ) {
            return new WP_Error('not_found', __('Post not found', 'schemafy'), array('status' => 404));
        }
        if ( ! current_user_can('edit_post', $post_id) ) {
            return new WP_Error('forbidden', __('You cannot edit this post', 'schemafy'), array('status' => 403));
        }

        global $schemafy_core_instance;
        if ( ! $schemafy_core_instance ) {
            return new WP_Error('not_ready', __('Plugin not initialized', 'schemafy'), array('status' => 503));
        }

        $generator = $schemafy_core_instance->get_auto_generator();
        if ( ! $generator ) {
            return new WP_Error('not_ready', __('Auto generator not available', 'schemafy'), array('status' => 503));
        }

        $result = $generator->analyze_post($post_id);

        return rest_ensure_response(array(
            'post_id'         => $post_id,
            'word_count'      => $result['word_count']       ?? 0,
            'existing'        => $result['existing_schemas'] ?? array(),
            'recommendations' => $result['recommended']      ?? array(),
        ));
    }

    /**
     * Canonize URL to HTTPS if site uses HTTPS
     *
     * @param string $url URL to canonize
     * @return string Canonized URL
     */
    private function canonize_url_https($url) {
        $site_parsed = wp_parse_url(home_url());
        $input_parsed = wp_parse_url($url);
        
        if (!$input_parsed || !isset($input_parsed['host'])) {
            return $url;
        }
        
        // Detect if home_url() uses HTTPS
        $site_is_https = ($site_parsed['scheme'] === 'https');
        
        // Detect if it's development environment
        $input_host = strtolower($input_parsed['host']);
        $is_dev_host = (
            $input_host === 'localhost' ||
            $input_host === '127.0.0.1' ||
            (substr_compare($input_host, '.test', -5) === 0) ||
            (substr_compare($input_host, '.local', -6) === 0)
        );
        
        // Canonize to HTTPS if site is HTTPS and NOT development
        if ($site_is_https && !$is_dev_host && $input_parsed['scheme'] === 'http') {
            // Rebuild URL with HTTPS maintaining host/path/query/fragment
            $url = 'https://' . $input_parsed['host'];
            if (isset($input_parsed['path'])) $url .= $input_parsed['path'];
            if (isset($input_parsed['query'])) $url .= '?' . $input_parsed['query'];
            if (isset($input_parsed['fragment'])) $url .= '#' . $input_parsed['fragment'];
        }
        
        return $url;
    }
}