<?php
namespace WebshoptigerCatalogSync;

defined( 'ABSPATH' ) || exit;

/**
 * REST API endpoint on DESTINATION sites:
 *   POST /wp-json/webshoptigercatalogsync-sync/v1/status  – health check
 *
 * The actual product push uses the standard WooCommerce REST API (wc/v3/products).
 * This endpoint provides additional sync-specific features.
 *
 * On SOURCE site: admin AJAX handlers for manual sync trigger and log clear.
 */
class RestAPI {

    public static function init(): void {
        add_action( 'rest_api_init', [ __CLASS__, 'register_routes' ] );
        // Store the source URL as meta when WooCommerce downloads an image (destination site only)
        if ( ! Settings::is_source_site() ) {
            add_filter( 'wp_handle_sideload_prefilter', [ __CLASS__, 'capture_sideload_prefilter' ] );
            add_action( 'add_attachment', [ __CLASS__, 'save_attachment_source_url' ] );
        }
        // Save site type — available on both sites
        add_action( 'wp_ajax_webshoptigercatalogsync_save_sitetype', [ __CLASS__, 'ajax_save_sitetype' ] );

        // Source-site-specific AJAX handlers — only registered if the classes are available
        if ( Settings::is_source_site() ) {
            add_action( 'wp_ajax_webshoptigercatalogsync_manual',         [ __CLASS__, 'ajax_manual_sync' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_clear_log',      [ __CLASS__, 'ajax_clear_log' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_test_site',      [ __CLASS__, 'ajax_test_site' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_save_settings',  [ __CLASS__, 'ajax_save_settings' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_save_site',      [ __CLASS__, 'ajax_save_site' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_delete_site',    [ __CLASS__, 'ajax_delete_site' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_sync_site',      [ __CLASS__, 'ajax_sync_site' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_search_products',     [ __CLASS__, 'ajax_search_products' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_sync_single_product', [ __CLASS__, 'ajax_sync_single_product' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_job_status',     [ __CLASS__, 'ajax_job_status' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_cancel_job',     [ __CLASS__, 'ajax_cancel_job' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_resume_job',     [ __CLASS__, 'ajax_resume_job' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_clear_jobs',     [ __CLASS__, 'ajax_clear_jobs' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_save_batch_size',    [ __CLASS__, 'ajax_save_batch_size' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_clear_cat_cache',    [ __CLASS__, 'ajax_clear_cat_cache' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_clear_brand_cache',  [ __CLASS__, 'ajax_clear_brand_cache' ] );
            add_action( 'wp_ajax_webshoptigercatalogsync_reset_remote_ids',     [ __CLASS__, 'ajax_reset_remote_ids' ] );
        }
    }

    // -------------------------------------------------------------------------
    // REST endpoint (destination site health check)
    // -------------------------------------------------------------------------

    public static function register_routes(): void {
        register_rest_route( 'webshoptigercatalogsync-sync/v1', '/status', [
            'methods'             => 'GET',
            'callback'            => [ __CLASS__, 'rest_status' ],
            'permission_callback' => '__return_true',
        ] );

        // Queue runner endpoint — replaces the standalone runner.php file.
        // Secured by a secret token stored in wp_options (webshoptigercatalogsync_runner_token).
        register_rest_route( 'webshoptigercatalogsync-sync/v1', '/run-queue', [
            'methods'             => 'POST',
            'callback'            => [ __CLASS__, 'rest_run_queue' ],
            'permission_callback' => function( \WP_REST_Request $request ) {
                $token       = sanitize_text_field( $request->get_param( 'token' ) ?? '' );
                $saved_token = get_option( 'webshoptigercatalogsync_runner_token', '' );
                return ! empty( $saved_token ) && hash_equals( $saved_token, $token );
            },
        ] );

        // Endpoint to check whether images already exist in the media library
        register_rest_route( 'webshoptigercatalogsync-sync/v1', '/resolve-images', [
            'methods'             => 'POST',
            'callback'            => [ __CLASS__, 'rest_resolve_images' ],
            'permission_callback' => function() {
                // Must have upload_files capability — this covers media management.
                // Per-attachment permission is enforced inside the callback itself.
                return current_user_can( 'upload_files' );
            },
        ] );

        // Endpoint to link brand terms directly to a product on the destination site
        register_rest_route( 'webshoptigercatalogsync-sync/v1', '/assign-brands', [
            'methods'             => 'POST',
            'callback'            => [ __CLASS__, 'rest_assign_brands' ],
            'permission_callback' => function( \WP_REST_Request $request ) {
                // Must have generic edit_products capability
                if ( ! current_user_can( 'edit_products' ) ) {
                    return false;
                }
                // Also verify permission for the specific product being modified
                $product_id = absint( $request->get_param( 'product_id' ) );
                if ( $product_id > 0 && ! current_user_can( 'edit_post', $product_id ) ) {
                    return false;
                }
                return true;
            },
        ] );
    }

    public static function rest_assign_brands( \WP_REST_Request $request ): \WP_REST_Response {
        $product_id  = (int) $request->get_param( 'product_id' );
        $term_ids    = array_map( 'absint', (array) $request->get_param( 'term_ids' ) );
        $term_slugs  = array_map( 'sanitize_text_field', (array) $request->get_param( 'term_slugs' ) );

        if ( ! $product_id ) {
            return new \WP_REST_Response( [ 'success' => false, 'message' => 'product_id is missing.' ], 400 );
        }

        $product = wc_get_product( $product_id );
        if ( ! $product ) {
            return new \WP_REST_Response( [ 'success' => false, 'message' => 'Product not found.' ], 404 );
        }

        // Make sure the taxonomy exists
        BrandSync::maybe_register_taxonomy();

        // Create terms that don't exist yet, based on slugs
        $final_term_ids = $term_ids;
        foreach ( $term_slugs as $i => $slug ) {
            if ( empty( $slug ) ) continue;
            $existing = get_term_by( 'slug', $slug, BrandSync::TAXONOMY );
            if ( $existing ) {
                $final_term_ids[] = $existing->term_id;
            }
        }

        $final_term_ids = array_unique( array_filter( $final_term_ids ) );

        if ( empty( $final_term_ids ) ) {
            return new \WP_REST_Response( [ 'success' => false, 'message' => 'No valid term IDs.' ], 400 );
        }

        // Link terms to the product
        $result = wp_set_object_terms( $product_id, $final_term_ids, BrandSync::TAXONOMY );

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

        return new \WP_REST_Response( [
            'success'  => true,
            'message'  => 'Brands linked.',
            'term_ids' => $final_term_ids,
        ] );
    }

    public static function rest_run_queue( \WP_REST_Request $request ): \WP_REST_Response {
        if ( class_exists( 'WebshoptigerCatalogSync\\Queue' ) ) {
            \WebshoptigerCatalogSync\Queue::process_batch();
        }
        return new \WP_REST_Response( [ 'success' => true ], 200 );
    }

    public static function rest_status( \WP_REST_Request $request ): \WP_REST_Response {
        return new \WP_REST_Response( [
            'plugin'     => WEBSHOPTIGERCATALOGSYNC_PLUGIN_SLUG,
            'version'    => WEBSHOPTIGERCATALOGSYNC_VERSION,
            'woocommerce' => class_exists( 'WooCommerce' ) ? WC()->version : null,
            'site_url'   => get_site_url(),
        ] );
    }

    /**
     * Check which images already exist in the media library.
     *
     * Request body: { "urls": ["https://...", "https://..."] }
     * Response:     { "found": { "https://...": 42, ... }, "missing": ["https://..."] }
     *
     * Images are identified via the _sc_source_url attachment meta that the
     * source site sends along with every image.
     */
    public static function rest_resolve_images( \WP_REST_Request $request ): \WP_REST_Response {
        global $wpdb;

        $urls = array_filter( array_map( 'esc_url_raw', (array) $request->get_param( 'urls' ) ) );

        if ( empty( $urls ) ) {
            return new \WP_REST_Response( [ 'found' => [], 'missing' => [] ] );
        }

        $found   = [];
        $missing = [];

        foreach ( $urls as $url ) {
            // Look up the attachment based on the _sc_source_url meta
            // phpcs:ignore // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $attachment_id = (int) $wpdb->get_var( $wpdb->prepare(
                "SELECT post_id FROM {$wpdb->postmeta}
                 WHERE meta_key = '_sc_source_url' AND meta_value = %s
                 LIMIT 1",
                $url
            ) );

            if ( $attachment_id ) {
                // Double-check the attachment still exists
                if ( get_post( $attachment_id ) ) {
                    $found[ $url ] = $attachment_id;
                    continue;
                }
            }

            // Fallback: look up by guid (original URL) or filename
            $filename = basename( wp_parse_url( $url, PHP_URL_PATH ) );
            if ( $filename ) {
                // phpcs:ignore // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $attachment_id = (int) $wpdb->get_var( $wpdb->prepare(
                    "SELECT ID FROM {$wpdb->posts}
                     WHERE post_type = 'attachment'
                     AND post_status = 'inherit'
                     AND (guid LIKE %s OR post_name = %s)
                     LIMIT 1",
                    '%' . $wpdb->esc_like( $filename ),
                    pathinfo( $filename, PATHINFO_FILENAME )
                ) );

                if ( $attachment_id ) {
                    // Only update meta if the current user can edit this specific attachment
                    if ( current_user_can( 'edit_post', $attachment_id ) ) {
                        update_post_meta( $attachment_id, '_sc_source_url', $url );
                    }
                    $found[ $url ] = $attachment_id;
                    continue;
                }
            }

            $missing[] = $url;
        }

        return new \WP_REST_Response( [
            'found'   => $found,
            'missing' => $missing,
        ] );
    }

    // -------------------------------------------------------------------------
    // AJAX: manual full sync
    // -------------------------------------------------------------------------

    public static function ajax_manual_sync(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        Sync::run_all();
        wp_send_json_success( 'Synchronization started.' );
    }

    // -------------------------------------------------------------------------
    // AJAX: sync single site
    // -------------------------------------------------------------------------

    public static function ajax_sync_site(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $site_id = absint( $_POST['site_id'] ?? 0 );
        Sync::sync_site( $site_id );
        wp_send_json_success( 'Synchronization started for site #' . $site_id . '.' );
    }

    // -------------------------------------------------------------------------
    // AJAX: search products for manual product selection
    // -------------------------------------------------------------------------

    public static function ajax_search_products(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $term = sanitize_text_field( wp_unslash( $_POST['term'] ?? '' ));
        if ( strlen( $term ) < 2 ) {
            wp_send_json_success( [] );
            return;
        }

        wp_send_json_success( Queue::search_products( $term ) );
    }

    // -------------------------------------------------------------------------
    // AJAX: sync one specific product
    // -------------------------------------------------------------------------

    public static function ajax_sync_single_product(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $product_id = absint( $_POST['product_id'] ?? 0 );
        if ( ! $product_id ) {
            wp_send_json_error( 'No product selected.' );
        }

        $site_id = isset( $_POST['site_id'] ) && $_POST['site_id'] !== '' ? absint( $_POST['site_id'] ) : null;

        $result = Queue::enqueue_single_product( $product_id, $site_id );

        if ( is_wp_error( $result ) ) {
            wp_send_json_error( $result->get_error_message() );
        }

        wp_send_json_success( [ 'message' => 'Product queued for synchronization.', 'job_id' => $result ] );
    }

    // -------------------------------------------------------------------------
    // AJAX: clear log
    // -------------------------------------------------------------------------

    public static function ajax_clear_log(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );
        Sync::clear_log();
        wp_send_json_success( 'Log cleared.' );
    }

    // -------------------------------------------------------------------------
    // AJAX: test remote site connection
    // -------------------------------------------------------------------------

    public static function ajax_test_site(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $url        = esc_url_raw( wp_unslash( $_POST['site_url'] ?? '' ), [ 'https', 'http' ] );
        $api_key    = sanitize_text_field( wp_unslash( $_POST['api_key'] ?? '' ) );
        $api_secret = sanitize_text_field( wp_unslash( $_POST['api_secret'] ?? '' ) );

        if ( ! preg_match( '#^https?://#i', $url ) ) {
            wp_send_json_error( 'Site URL must start with http:// or https://.' );
        }

        $credentials = base64_encode( $api_key . ':' . $api_secret );

        // Try all known endpoint slugs for backwards compatibility with older versions
        $endpoints = [
            trailingslashit( $url ) . 'wp-json/webshoptigercatalogsync-sync/v1/status',
            trailingslashit( $url ) . 'wp-json/wbcsync-sync/v1/status',
            trailingslashit( $url ) . 'wp-json/wcss-sync/v1/status',
            trailingslashit( $url ) . 'wp-json/ssfw-sync/v1/status',
        ];

        $last_code = 0;
        foreach ( $endpoints as $endpoint ) {
            $response = wp_remote_get( $endpoint, [
                'timeout' => 10,
                'headers' => [ 'Authorization' => 'Basic ' . $credentials ],
            ] );

            if ( is_wp_error( $response ) ) continue;

            $code = (int) wp_remote_retrieve_response_code( $response );
            $last_code = $code;

            if ( $code === 200 ) {
                $body = json_decode( wp_remote_retrieve_body( $response ), true );
                $wc_version = $body['woocommerce'] ?? 'unknown';
                if ( isset( $body['woocommerce'] ) || isset( $body['plugin'] ) ) {
                    wp_send_json_success( 'Connection successful. WooCommerce ' . $wc_version );
                }
            }
        }

        // Fallback: check WooCommerce REST API directly
        $wc_endpoint = trailingslashit( $url ) . 'wp-json/wc/v3/system_status';
        $wc_response = wp_remote_get( $wc_endpoint, [
            'timeout' => 10,
            'headers' => [ 'Authorization' => 'Basic ' . $credentials ],
        ] );

        if ( ! is_wp_error( $wc_response ) && (int) wp_remote_retrieve_response_code( $wc_response ) === 200 ) {
            wp_send_json_success( 'WooCommerce connection successful. Make sure the plugin is also installed on the destination site.' );
        }

        wp_send_json_error( 'Connection failed (HTTP ' . $last_code . '). Check the URL, API credentials, and whether WooCommerce is active on the destination site.' );
    }

    // -------------------------------------------------------------------------
    // AJAX: test OpenAI key


    // -------------------------------------------------------------------------
    // AJAX: save general settings
    // -------------------------------------------------------------------------

    public static function ajax_save_settings(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        update_option( 'webshoptigercatalogsync_openai_key',    sanitize_text_field( wp_unslash( $_POST['openai_key'] ?? '' ) ));
        update_option( 'webshoptigercatalogsync_openai_prompt', sanitize_textarea_field( wp_unslash( $_POST['openai_prompt'] ?? '' ) ));

        // Pro-only: rewriting descriptions via OpenAI.
        $rewrite_requested = absint( $_POST['rewrite_descriptions'] ?? 0 );
        update_option( 'webshoptigercatalogsync_rewrite_descriptions', Settings::is_pro() ? $rewrite_requested : 0 );

        // Sync interval — available to all users.
        $new_interval = sanitize_key( wp_unslash( $_POST['interval'] ?? 'hourly' ) );
        $old_interval = Settings::get( 'interval' );
        update_option( 'webshoptigercatalogsync_interval', $new_interval );

        if ( $new_interval !== $old_interval ) {
            Scheduler::reschedule();
        }

        $message = 'Settings saved.';
        if ( ! Settings::is_pro() && $rewrite_requested ) {
            $message .= ' Note: OpenAI description rewriting is a Pro feature.';
        }

        wp_send_json_success( $message );
    }

    // -------------------------------------------------------------------------
    // AJAX: save (create/update) site
    // -------------------------------------------------------------------------

    public static function ajax_save_site(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $data = [
            'id'              => absint( wp_unslash( $_POST['id'] ?? 0 ) ),
            'label'           => sanitize_text_field( wp_unslash( $_POST['label'] ?? '' ) ),
            'site_url'        => esc_url_raw( wp_unslash( $_POST['site_url'] ?? '' ), [ 'https', 'http' ] ),
            'api_key'         => sanitize_text_field( wp_unslash( $_POST['api_key'] ?? '' ) ),
            'api_secret'      => sanitize_text_field( wp_unslash( $_POST['api_secret'] ?? '' ) ),
            'categories'      => array_map( 'absint', (array) ( $_POST['categories'] ?? [] ) ),
            'enabled'         => absint( $_POST['enabled'] ?? 0 ),
            'sync_description'=> absint( $_POST['sync_description'] ?? 1 ),
            // Pro-only fields — silently ignored if not Pro
            'sync_interval'   => Settings::is_pro() ? sanitize_key( wp_unslash( $_POST['sync_interval'] ?? 'global' ) ) : 'global',
            'price_adjustment'=> Settings::is_pro() ? sanitize_key( wp_unslash( $_POST['price_adjustment'] ?? 'none' ) ) : 'none',
            'price_value'     => Settings::is_pro() ? (float) wp_unslash( $_POST['price_value'] ?? 0 ) : 0,
            'sync_fields'     => Settings::is_pro() && isset( $_POST['sync_fields'] ) && is_array( $_POST['sync_fields'] )
                                    ? array_map( 'sanitize_key', wp_unslash( $_POST['sync_fields'] ) )
                                    : null,
            'report_email'    => Settings::is_pro() ? sanitize_email( wp_unslash( $_POST['report_email'] ?? '' ) ) : '',
        ];

        $result = SiteManager::save( $data );
        if ( is_wp_error( $result ) ) {
            wp_send_json_error( $result->get_error_message() );
        }
        wp_send_json_success( [ 'id' => $result, 'message' => 'Website saved.' ] );
    }

    // -------------------------------------------------------------------------
    // AJAX: delete site
    // -------------------------------------------------------------------------

    public static function ajax_delete_site(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $id = absint( $_POST['id'] ?? 0 );
        SiteManager::delete( $id );
        wp_send_json_success( 'Website deleted.' );
    }

    // -------------------------------------------------------------------------
    // AJAX: save report settings


    // -------------------------------------------------------------------------
    // AJAX: send test report


    // -------------------------------------------------------------------------
    // AJAX: regenerate description


    // -------------------------------------------------------------------------
    // AJAX: delete cached description


    // -------------------------------------------------------------------------
    // AJAX: save source/destination site setting
    // -------------------------------------------------------------------------

    public static function ajax_save_sitetype(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $is_source = absint( $_POST['is_source'] ?? 0 );
        update_option( 'webshoptigercatalogsync_is_source', $is_source );

        // Reschedule cron if the role changes
        if ( $is_source ) {
            Scheduler::reschedule();
        } else {
            Scheduler::unschedule();
        }

        wp_send_json_success( 'Role saved. Reloading page.' );
    }

    // -------------------------------------------------------------------------
    // AJAX: fetch job progress (polling)
    // -------------------------------------------------------------------------

    public static function ajax_job_status(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );
        wp_send_json_success( Queue::get_active_jobs() );
    }

    // -------------------------------------------------------------------------
    // AJAX: cancel job
    // -------------------------------------------------------------------------

    public static function ajax_cancel_job(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );
        $job_id = sanitize_text_field( wp_unslash( $_POST['job_id'] ?? '' ));
        if ( $job_id ) Queue::cancel_job( $job_id );
        wp_send_json_success( 'Job cancelled.' );
    }

    // -------------------------------------------------------------------------
    // AJAX: clean up completed jobs
    // -------------------------------------------------------------------------

    public static function ajax_clear_jobs(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );
        Queue::clear_finished_jobs();
        wp_send_json_success( 'Completed jobs removed.' );
    }

    public static function ajax_save_batch_size(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );
        $size = max( 1, min( 50, absint( $_POST['batch_size'] ?? 10 ) ) );
        update_option( 'webshoptigercatalogsync_batch_size', $size );
        wp_send_json_success( 'Batch size saved: ' . $size );
    }

    public static function ajax_resume_job(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );
        $job_id = sanitize_text_field( wp_unslash( $_POST['job_id'] ?? '' ));
        if ( ! $job_id ) wp_send_json_error( 'No job_id.' );
        Queue::resume_job( $job_id );
        wp_send_json_success( 'Synchronization resumed.' );
    }

    // -------------------------------------------------------------------------
    // Store source URL on sideload (image download via WooCommerce REST API)
    // -------------------------------------------------------------------------

    private static $pending_source_url = '';

    public static function capture_sideload_prefilter( array $file ): array {
        // The URL is temporarily available in $_REQUEST when WooCommerce downloads an image
        $src = sanitize_url( wp_unslash( $_REQUEST['src'] ?? '' ) );
        if ( $src ) {
            self::$pending_source_url = $src;
        }
        return $file;
    }

    public static function save_attachment_source_url( int $attachment_id ): void {
        if ( ! empty( self::$pending_source_url ) ) {
            update_post_meta( $attachment_id, '_sc_source_url', self::$pending_source_url );
            self::$pending_source_url = '';
        }
    }

    public static function ajax_clear_cat_cache(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $sites = SiteManager::get_all();
        foreach ( $sites as $site ) {
            CategorySync::clear_cache( (int) $site['id'] );
        }

        wp_send_json_success( 'Category cache cleared for ' . count( $sites ) . ' site(s). The next sync will look up all categories again.' );
    }

    public static function ajax_clear_brand_cache(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $sites = SiteManager::get_all();
        foreach ( $sites as $site ) {
            BrandSync::clear_cache( (int) $site['id'] );
        }

        wp_send_json_success( 'Brand cache cleared for ' . count( $sites ) . ' site(s).' );
    }

    // -------------------------------------------------------------------------
    // AJAX: reset remote IDs for a site
    // -------------------------------------------------------------------------

    public static function ajax_reset_remote_ids(): void {
        check_ajax_referer( 'webshoptigercatalogsync_nonce', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'No permission.' );

        $site_id = absint( $_POST['site_id'] ?? 0 );
        if ( ! $site_id ) wp_send_json_error( 'No site ID provided.' );

        $site = SiteManager::get( $site_id );
        if ( ! $site ) wp_send_json_error( 'Site not found.' );

        $cleared = Sync::clear_remote_ids_for_site( $site_id );

        wp_send_json_success( sprintf(
            'Sync state reset for "%s". %d product link(s) cleared. The next sync will re-create all products on the destination site.',
            esc_html( $site['label'] ),
            $cleared
        ) );
    }
}
