<?php
defined( 'ABSPATH' ) || exit;

class SITECL_REST_Controller {

    private const NAMESPACE = 'site-cliniq/v1';

    public static function register_routes(): void {
        // Run full scan.
        register_rest_route( self::NAMESPACE, '/scan', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'run_scan' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Get last scan results.
        register_rest_route( self::NAMESPACE, '/scan/results', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_results' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Get health score history.
        register_rest_route( self::NAMESPACE, '/health-score', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_health_score' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Alt tag audit data.
        register_rest_route( self::NAMESPACE, '/alt-tags', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_alt_tags' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Save alt text for a single attachment.
        register_rest_route( self::NAMESPACE, '/alt-tags/(?P<id>\d+)', [
            'methods'             => WP_REST_Server::EDITABLE,
            'callback'            => [ __CLASS__, 'save_alt_text' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'id'       => [ 'validate_callback' => fn( $v ) => is_numeric( $v ) ],
                'alt_text' => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ],
            ],
        ] );

        // Send email report.
        register_rest_route( self::NAMESPACE, '/report/send', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'send_report' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Get settings.
        register_rest_route( self::NAMESPACE, '/settings', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_settings' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Save settings.
        register_rest_route( self::NAMESPACE, '/settings', [
            'methods'             => WP_REST_Server::EDITABLE,
            'callback'            => [ __CLASS__, 'save_settings' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Error dashboard — available in both free and pro.
        register_rest_route( self::NAMESPACE, '/error-dashboard', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_error_dashboard' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Plugin backups — list available rollback points.
        register_rest_route( self::NAMESPACE, '/plugin-backups', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_plugin_backups' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'plugin_slug' => [
                    'default'           => null,
                    'sanitize_callback' => 'sanitize_key',
                ],
            ],
        ] );

        // Plugin backups — trigger a rollback.
        register_rest_route( self::NAMESPACE, '/plugin-backups/rollback', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'rollback_plugin' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Plugin backups — delete a backup.
        register_rest_route( self::NAMESPACE, '/plugin-backups/delete', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'delete_plugin_backup' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // Plugin backups — manually trigger backup of a specific plugin right now.
        register_rest_route( self::NAMESPACE, '/plugin-backups/create', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'create_plugin_backup' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO routes — only registered when PRO classes are present.
        if ( ! class_exists( 'SITECL_Alt_Generator' ) ) {
            return;
        }

        // PRO: Generate alt text for a single attachment via Claude Vision.
        register_rest_route( self::NAMESPACE, '/alt-tags/generate/(?P<id>\d+)', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'generate_alt_text' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'id'           => [ 'validate_callback' => fn( $v ) => is_numeric( $v ) ],
                'context_hint' => [ 'default' => '', 'sanitize_callback' => 'sanitize_text_field' ],
            ],
        ] );

        // PRO: Bulk generate alt text for all missing attachments.
        register_rest_route( self::NAMESPACE, '/alt-tags/generate-bulk', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'generate_alt_bulk' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Get all 301 redirects.
        register_rest_route( self::NAMESPACE, '/redirects', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_redirects' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Add a 301 redirect.
        register_rest_route( self::NAMESPACE, '/redirects', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'add_redirect' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'from' => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ],
                'to'   => [ 'required' => true, 'sanitize_callback' => 'esc_url_raw' ],
            ],
        ] );

        // PRO: Delete a redirect.
        register_rest_route( self::NAMESPACE, '/redirects/delete', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'delete_redirect' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'from' => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ],
            ],
        ] );

        // PRO: AI SEO fix suggestion for a single issue.
        register_rest_route( self::NAMESPACE, '/seo/fix', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'seo_fix_suggestion' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'type'   => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ],
                'title'  => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ],
                'detail' => [ 'default'  => '', 'sanitize_callback' => 'sanitize_text_field' ],
            ],
        ] );

        // PRO: Performance — run PageSpeed analysis.
        register_rest_route( self::NAMESPACE, '/performance', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'run_performance' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'url'      => [ 'default' => '', 'sanitize_callback' => 'esc_url_raw' ],
                'strategy' => [ 'default' => 'mobile', 'sanitize_callback' => 'sanitize_text_field' ],
            ],
        ] );

        // PRO: Auto-fix — list available fixes.
        register_rest_route( self::NAMESPACE, '/fixes', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_fixes' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Auto-fix — apply a fix.
        register_rest_route( self::NAMESPACE, '/fixes/apply', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'apply_fix' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'fix_key' => [ 'required' => true, 'sanitize_callback' => 'sanitize_key' ],
            ],
        ] );

        // PRO: Auto-fix — rollback a fix.
        register_rest_route( self::NAMESPACE, '/fixes/rollback', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'rollback_fix' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'log_index' => [ 'required' => true, 'validate_callback' => fn( $v ) => is_numeric( $v ) ],
            ],
        ] );

        // PRO: Auto-fix — get fix log.
        register_rest_route( self::NAMESPACE, '/fixes/log', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_fix_log' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Predictive alerts.
        register_rest_route( self::NAMESPACE, '/predictive', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_predictive' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Site snapshot — take.
        register_rest_route( self::NAMESPACE, '/snapshot', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'take_snapshot' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Site snapshot — get current.
        register_rest_route( self::NAMESPACE, '/snapshot', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_snapshot' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Site snapshot — Q&A cache.
        register_rest_route( self::NAMESPACE, '/snapshot/qa', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_snapshot_qa' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Fix AI review.
        register_rest_route( self::NAMESPACE, '/fixes/ai-review', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'ai_review_fix' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'fix_key' => [ 'required' => true, 'sanitize_callback' => 'sanitize_key' ],
            ],
        ] );

        // PRO: Scheduled scan status.
        register_rest_route( self::NAMESPACE, '/schedule', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_schedule' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Trigger scan now from schedule panel.
        register_rest_route( self::NAMESPACE, '/schedule/run', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'run_scan_now' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: AI Chat — load history for current user.
        register_rest_route( self::NAMESPACE, '/chat/history', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'chat_history' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: AI Chat — send a message (history loaded from DB server-side).
        register_rest_route( self::NAMESPACE, '/chat', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'chat' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'message' => [ 'required' => true, 'sanitize_callback' => 'sanitize_textarea_field' ],
            ],
        ] );

        // PRO: AI Chat — clear history.
        register_rest_route( self::NAMESPACE, '/chat/clear', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'chat_clear' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
        ] );

        // PRO: Fix diff preview.
        register_rest_route( self::NAMESPACE, '/fixes/preview', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [ __CLASS__, 'preview_fix' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'fix_key' => [ 'required' => true, 'sanitize_callback' => 'sanitize_key' ],
            ],
        ] );

        // Update risk for a single plugin.
        register_rest_route( self::NAMESPACE, '/update-risk/(?P<slug>[a-z0-9-]+)', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [ __CLASS__, 'get_update_risk' ],
            'permission_callback' => [ __CLASS__, 'admin_only' ],
            'args'                => [
                'slug'    => [ 'validate_callback' => fn( $v ) => (bool) preg_match( '/^[a-z0-9-]+$/', $v ) ],
                'old_ver' => [ 'required' => true ],
                'new_ver' => [ 'required' => true ],
            ],
        ] );
    }

    // -------------------------------------------------------------------------
    // Callbacks
    // -------------------------------------------------------------------------

    public static function run_scan( WP_REST_Request $request ): WP_REST_Response {
        $result = SITECL_Scanner::run_full_scan();
        // Always update the site snapshot after a manual scan so AI Chat context stays current.
        if ( class_exists( 'SITECL_Site_Snapshot' ) ) {
            SITECL_Site_Snapshot::take();
        }
        return rest_ensure_response( $result );
    }

    public static function get_results( WP_REST_Request $request ): WP_REST_Response {
        $last = get_option( 'sitecl_last_scan', [] );
        return rest_ensure_response( $last );
    }

    public static function get_health_score( WP_REST_Request $request ): WP_REST_Response {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $rows = $wpdb->get_results(
            "SELECT grade, score, scanned_at FROM {$wpdb->prefix}sitecl_health_scores ORDER BY scanned_at DESC LIMIT 28", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            ARRAY_A
        );
        return rest_ensure_response( $rows );
    }

    public static function get_alt_tags( WP_REST_Request $request ): WP_REST_Response {
        $audit = SITECL_Alt_Scanner::get_full_audit();
        return rest_ensure_response( $audit );
    }

    public static function save_alt_text( WP_REST_Request $request ): WP_REST_Response {
        $id       = (int) $request->get_param( 'id' );
        $alt_text = (string) $request->get_param( 'alt_text' );
        $success  = SITECL_Alt_Scanner::save_alt_text( $id, $alt_text );

        if ( ! $success ) {
            return new WP_REST_Response( [ 'error' => __( 'Insufficient permissions.', 'site-cliniq' ) ], 403 );
        }

        return rest_ensure_response( [ 'saved' => true, 'id' => $id, 'alt_text' => $alt_text ] );
    }

    public static function send_report( WP_REST_Request $request ): WP_REST_Response {
        $result = SITECL_Email_Report::send_now();

        if ( is_wp_error( $result ) ) {
            return new WP_REST_Response( [ 'error' => $result->get_error_message() ], 500 );
        }

        return rest_ensure_response( [ 'sent' => true ] );
    }

    public static function get_settings( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( [
            'claude_api_key' => '' !== get_option( 'sitecl_claude_api_key', '' ) ? '***' : '',
            'psi_api_key'    => '' !== get_option( 'sitecl_psi_api_key', '' ) ? '***' : '',
            'auto_scan'      => get_option( 'sitecl_auto_scan', 'off' ),
            'auto_email'     => get_option( 'sitecl_auto_email', 'off' ),
            'guardian_mode'  => get_option( 'sitecl_guardian_mode', 'off' ),
        ] );
    }

    public static function save_settings( WP_REST_Request $request ): WP_REST_Response {
        $params = $request->get_json_params();

        if ( ! empty( $params['claude_api_key'] ) && $params['claude_api_key'] !== '***' ) {
            update_option( 'sitecl_claude_api_key', sanitize_text_field( $params['claude_api_key'] ) );
        }

        if ( ! empty( $params['psi_api_key'] ) && $params['psi_api_key'] !== '***' ) {
            update_option( 'sitecl_psi_api_key', sanitize_text_field( $params['psi_api_key'] ) );
        }

        $valid_schedules = [ 'off', 'daily', 'weekly' ];

        if ( isset( $params['auto_scan'] ) && in_array( $params['auto_scan'], $valid_schedules, true ) ) {
            $schedule = $params['auto_scan'];
            update_option( 'sitecl_auto_scan', $schedule );
            wp_clear_scheduled_hook( 'sitecl_scheduled_scan' );
            if ( 'off' !== $schedule ) {
                wp_schedule_event( time(), $schedule, 'sitecl_scheduled_scan' );
            }
        }

        if ( isset( $params['auto_email'] ) && in_array( $params['auto_email'], [ 'off', 'weekly' ], true ) ) {
            $email_schedule = $params['auto_email'];
            update_option( 'sitecl_auto_email', $email_schedule );
            wp_clear_scheduled_hook( 'sitecl_scheduled_email' );
            if ( 'off' !== $email_schedule ) {
                wp_schedule_event( time(), 'weekly', 'sitecl_scheduled_email' );
            }
        }

        if ( isset( $params['guardian_mode'] ) && in_array( $params['guardian_mode'], [ 'off', 'ask', 'auto' ], true ) ) {
            $guardian_mode = $params['guardian_mode'];
            update_option( 'sitecl_guardian_mode', $guardian_mode );
            wp_clear_scheduled_hook( 'sitecl_guardian_check' );
            if ( 'off' !== $guardian_mode ) {
                if ( ! wp_next_scheduled( 'sitecl_guardian_check' ) ) {
                    wp_schedule_event( time(), 'every_minute', 'sitecl_guardian_check' );
                }
            }
        }

        return rest_ensure_response( [ 'saved' => true ] );
    }

    public static function get_update_risk( WP_REST_Request $request ): WP_REST_Response {
        $slug    = (string) $request->get_param( 'slug' );
        $old_ver = (string) $request->get_param( 'old_ver' );
        $new_ver = (string) $request->get_param( 'new_ver' );

        if ( ! function_exists( 'get_plugins' ) ) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }

        $plugins     = get_plugins();
        $plugin_data = new stdClass();
        foreach ( $plugins as $file => $data ) {
            if ( str_starts_with( $file, $slug . '/' ) ) {
                $plugin_data->Name    = $data['Name'];
                $plugin_data->Version = $data['Version'];
                break;
            }
        }

        $risk = SITECL_Update_Risk::score_update( $slug, $old_ver, $new_ver, $plugin_data );
        return rest_ensure_response( $risk );
    }

    // -------------------------------------------------------------------------
    // PRO callbacks
    // -------------------------------------------------------------------------

    public static function generate_alt_text( WP_REST_Request $request ): WP_REST_Response {
        $id      = (int) $request->get_param( 'id' );
        $hint    = (string) $request->get_param( 'context_hint' );
        $result  = SITECL_Alt_Generator::generate( $id, $hint );

        if ( is_wp_error( $result ) ) {
            return new WP_REST_Response( [ 'error' => $result->get_error_message() ], 400 );
        }

        return rest_ensure_response( [ 'alt_text' => $result, 'id' => $id ] );
    }

    public static function generate_alt_bulk( WP_REST_Request $request ): WP_REST_Response {
        $results = SITECL_Alt_Generator::bulk_generate( 20 );
        $out     = [];
        foreach ( $results as $id => $val ) {
            $out[] = [
                'id'       => $id,
                'success'  => ! is_wp_error( $val ),
                'alt_text' => is_wp_error( $val ) ? null : $val,
                'error'    => is_wp_error( $val ) ? $val->get_error_message() : null,
            ];
        }
        return rest_ensure_response( [ 'results' => $out ] );
    }

    public static function get_redirects( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( SITECL_Redirect_Manager::get_all() );
    }

    public static function add_redirect( WP_REST_Request $request ): WP_REST_Response {
        $from    = (string) $request->get_param( 'from' );
        $to      = (string) $request->get_param( 'to' );
        $success = SITECL_Redirect_Manager::add( $from, $to );
        return rest_ensure_response( [ 'saved' => $success ] );
    }

    public static function delete_redirect( WP_REST_Request $request ): WP_REST_Response {
        $from    = (string) $request->get_param( 'from' );
        $success = SITECL_Redirect_Manager::remove( $from );
        return rest_ensure_response( [ 'deleted' => $success ] );
    }

    public static function seo_fix_suggestion( WP_REST_Request $request ): WP_REST_Response {
        $type   = (string) $request->get_param( 'type' );
        $title  = (string) $request->get_param( 'title' );
        $detail = (string) $request->get_param( 'detail' );
        $result = SITECL_SEO_AI::suggest_single( $type, $title, $detail );

        if ( is_wp_error( $result ) ) {
            return new WP_REST_Response( [ 'error' => $result->get_error_message() ], 400 );
        }

        return rest_ensure_response( [ 'fix' => $result ] );
    }

    public static function run_performance( WP_REST_Request $request ): WP_REST_Response {
        $url      = (string) $request->get_param( 'url' );
        $strategy = (string) $request->get_param( 'strategy' );
        $result   = SITECL_Performance::analyse( $url, $strategy );

        if ( is_wp_error( $result ) ) {
            return new WP_REST_Response( [ 'error' => $result->get_error_message() ], 400 );
        }

        return rest_ensure_response( $result );
    }

    public static function get_fixes( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( [
            'fixes' => SITECL_Auto_Fix::available_fixes(),
            'log'   => SITECL_Auto_Fix::get_log(),
        ] );
    }

    public static function apply_fix( WP_REST_Request $request ): WP_REST_Response {
        $key    = (string) $request->get_param( 'fix_key' );
        $result = SITECL_Auto_Fix::apply( $key );
        $status = $result['success'] ? 200 : 400;
        return new WP_REST_Response( $result, $status );
    }

    public static function rollback_fix( WP_REST_Request $request ): WP_REST_Response {
        $index  = (int) $request->get_param( 'log_index' );
        $result = SITECL_Auto_Fix::rollback( $index );
        $status = $result['success'] ? 200 : 400;
        return new WP_REST_Response( $result, $status );
    }

    public static function get_fix_log( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( SITECL_Auto_Fix::get_log() );
    }

    public static function get_predictive( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( SITECL_Predictive::run() );
    }

    public static function get_schedule( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( SITECL_Scheduled_Scan::get_status() );
    }

    public static function run_scan_now( WP_REST_Request $request ): WP_REST_Response {
        $result = SITECL_Scheduled_Scan::run_now();
        return rest_ensure_response( $result );
    }

    public static function chat_history( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( [
            'history' => SITECL_AI_Chat::load_history(),
        ] );
    }

    public static function chat( WP_REST_Request $request ): WP_REST_Response {
        $message = (string) $request->get_param( 'message' );
        // History is loaded from DB inside chat() — client sends message only.
        $result  = SITECL_AI_Chat::chat( $message );

        if ( is_wp_error( $result ) ) {
            return new WP_REST_Response( [ 'error' => $result->get_error_message() ], 400 );
        }

        return rest_ensure_response( $result );
    }

    public static function chat_clear( WP_REST_Request $request ): WP_REST_Response {
        SITECL_AI_Chat::clear_history();
        return rest_ensure_response( [ 'cleared' => true ] );
    }

    public static function preview_fix( WP_REST_Request $request ): WP_REST_Response {
        $key    = (string) $request->get_param( 'fix_key' );
        $result = SITECL_Auto_Fix::preview( $key );
        return rest_ensure_response( $result );
    }

    public static function take_snapshot( WP_REST_Request $request ): WP_REST_Response {
        $snapshot = SITECL_Site_Snapshot::take();
        return rest_ensure_response( [ 'taken' => true, 'taken_at' => $snapshot['taken_at'] ?? '' ] );
    }

    public static function get_snapshot( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( SITECL_Site_Snapshot::get() );
    }

    public static function get_snapshot_qa( WP_REST_Request $request ): WP_REST_Response {
        return rest_ensure_response( SITECL_Site_Snapshot::get_qa_cache() );
    }

    public static function ai_review_fix( WP_REST_Request $request ): WP_REST_Response {
        $key     = (string) $request->get_param( 'fix_key' );
        $preview = SITECL_Auto_Fix::preview( $key );
        $review  = SITECL_Auto_Fix::ai_review( $key, $preview['diff'] ?? [] );
        return rest_ensure_response( $review );
    }

    public static function get_error_dashboard( WP_REST_Request $request ): WP_REST_Response {
        $limit = max( 1, min( (int) ( $request->get_param( 'limit' ) ?? 200 ), 500 ) );

        return rest_ensure_response( [
            'errors'  => SITECL_Error_Log::get_all( $limit ),
            'summary' => SITECL_Error_Log::get_summary(),
        ] );
    }

    // -------------------------------------------------------------------------
    // Plugin backups
    // -------------------------------------------------------------------------

    public static function get_plugin_backups( WP_REST_Request $request ): WP_REST_Response {
        $slug    = $request->get_param( 'plugin_slug' ) ?: null;
        $backups = SITECL_Plugin_Backup::get_backups( $slug );

        return rest_ensure_response( [
            'backups' => $backups,
            'count'   => count( $backups ),
        ] );
    }

    public static function rollback_plugin( WP_REST_Request $request ): WP_REST_Response {
        $params      = $request->get_json_params();
        $plugin_slug = sanitize_key( $params['plugin_slug'] ?? '' );
        $backup_file = sanitize_file_name( $params['backup_file'] ?? '' );

        if ( ! $plugin_slug || ! $backup_file ) {
            return new WP_REST_Response( [ 'error' => 'plugin_slug and backup_file are required.' ], 400 );
        }

        $result = SITECL_Plugin_Backup::rollback( $plugin_slug, $backup_file );

        return rest_ensure_response( $result );
    }

    public static function delete_plugin_backup( WP_REST_Request $request ): WP_REST_Response {
        $params      = $request->get_json_params();
        $plugin_slug = sanitize_key( $params['plugin_slug'] ?? '' );
        $backup_file = sanitize_file_name( $params['backup_file'] ?? '' );

        if ( ! $plugin_slug || ! $backup_file ) {
            return new WP_REST_Response( [ 'error' => 'plugin_slug and backup_file are required.' ], 400 );
        }

        SITECL_Plugin_Backup::delete_backup( $plugin_slug, $backup_file );

        return rest_ensure_response( [ 'deleted' => true ] );
    }

    /**
     * Manually create a backup of a plugin right now (without waiting for an update).
     * Useful for "backup before I manually update" workflows.
     */
    public static function create_plugin_backup( WP_REST_Request $request ): WP_REST_Response {
        $params      = $request->get_json_params();
        $plugin_file = sanitize_text_field( $params['plugin_file'] ?? '' ); // e.g. 'woocommerce/woocommerce.php'

        if ( ! $plugin_file || ! str_contains( $plugin_file, '/' ) ) {
            return new WP_REST_Response( [ 'error' => 'plugin_file is required (e.g. woocommerce/woocommerce.php).' ], 400 );
        }

        $plugin_slug = explode( '/', $plugin_file )[0];
        $plugin_dir  = WP_PLUGIN_DIR . '/' . $plugin_slug;

        if ( ! is_dir( $plugin_dir ) ) {
            return new WP_REST_Response( [ 'error' => "Plugin directory not found: {$plugin_slug}" ], 404 );
        }

        if ( ! function_exists( 'get_plugin_data' ) ) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        $data    = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_file, false, false );
        $version = sanitize_text_field( $data['Version'] ?? 'manual' );

        $ok = SITECL_Plugin_Backup::create_backup( $plugin_slug, $plugin_file, $version );

        if ( ! $ok ) {
            return new WP_REST_Response( [ 'error' => 'Backup failed. Check that ZipArchive is available and the upload directory is writable.' ], 500 );
        }

        return rest_ensure_response( [
            'success'     => true,
            'plugin_slug' => $plugin_slug,
            'version'     => $version,
        ] );
    }

    // -------------------------------------------------------------------------

    public static function admin_only(): bool {
        return current_user_can( 'manage_options' );
    }
}
