<?php
/**
 * Spellmatic_Harper
 *
 * Phase 2: Serves the Harper WASM bridge for browser-side scanning.
 *
 * Harper (Apache-2.0) grammar engine runs entirely in the admin's browser:
 *   1. PHP /scan/start returns a list of posts + plain text.
 *   2. harper-bridge.js lints each text block using Harper WASM.
 *   3. PHP /scan/submit stores the results and returns the final list.
 *
 * harper.js delivery strategy:
 *   • A stable version of harper.js ships bundled inside assets/harper/.
 *   • Users can manually upgrade by downloading harper.js from the Harper npm
 *     package and uploading it to wp-content/uploads/spellmatic/harper.js.
 *   • The plugin detects the user-uploaded file and uses it automatically.
 *   • No external requests are made by the plugin for grammar engine updates.
 */

defined( 'ABSPATH' ) || exit;

class Spellmatic_Harper {

    /** Version of the harper.js file bundled with the plugin. */
    const BUNDLED_VERSION = '1.2.0';

    /** Option key storing the version string of a user-uploaded upgrade. */
    const OPT_UPGRADED_VERSION = 'spellmatic_harper_version';

    // ── Resolve the harper.js URL ────────────────────────────────────────────
    /**
     * Returns the URL for harper.js.
     *
     * Priority:
     *   1. User-upgraded file in wp-content/uploads/spellmatic/harper.js
     *   2. Bundled file in assets/harper/harper.js
     */
    public static function get_harper_url(): string {
        // Check for user-upgraded copy first.
        $upload_dir = wp_upload_dir();
        $upgraded   = $upload_dir['basedir'] . '/spellmatic/harper.js';
        if ( file_exists( $upgraded ) ) {
            return $upload_dir['baseurl'] . '/spellmatic/harper.js';
        }

        // Bundled fallback — always present in the plugin.
        $local = SPELLMATIC_DIR . 'assets/harper/harper.js';
        return file_exists( $local )
            ? SPELLMATIC_URL . 'assets/harper/harper.js'
            : '';
    }

    // ── Version info ─────────────────────────────────────────────────────────
    /**
     * Get the currently active Harper version.
     */
    public static function get_active_version(): string {
        return get_option( self::OPT_UPGRADED_VERSION, self::BUNDLED_VERSION );
    }

    /**
     * Get version info for the admin UI.
     */
    public static function get_version_info(): array {
        $active   = self::get_active_version();
        $upgraded = get_option( self::OPT_UPGRADED_VERSION, '' );

        return [
            'bundled'  => self::BUNDLED_VERSION,
            'active'   => $active,
            'upgraded' => $upgraded,
            'hasUpgrade' => ! empty( $upgraded ) && $upgraded !== self::BUNDLED_VERSION,
        ];
    }

    // ── REST: Revert to bundled version ──────────────────────────────────────
    /**
     * POST /spellmatic/v1/harper/revert
     * Removes the upgraded harper.js and reverts to the bundled version.
     */
    public static function revert_to_bundled(): \WP_REST_Response {
        $upload_dir  = wp_upload_dir();
        $target_file = $upload_dir['basedir'] . '/spellmatic/harper.js';

        if ( file_exists( $target_file ) ) {
            // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink
            @unlink( $target_file );
        }

        delete_option( self::OPT_UPGRADED_VERSION );

        return new \WP_REST_Response( [
            'success' => true,
            'version' => self::BUNDLED_VERSION,
        ] );
    }

    // ── Register REST routes ─────────────────────────────────────────────────
    public static function register_routes(): void {
        register_rest_route( 'spellmatic/v1', '/harper/revert', [
            'methods'             => 'POST',
            'callback'            => [ __CLASS__, 'revert_to_bundled' ],
            'permission_callback' => fn() => current_user_can( 'manage_options' ),
        ] );
    }

    // ── Enqueue Harper bridge for the admin dashboard ─────────────────────────
    public static function enqueue(): void {

        wp_enqueue_script(
            'harper-bridge',
            SPELLMATIC_URL . 'assets/harper/harper-bridge.js',
            [],
            SPELLMATIC_VERSION,
            true
        );

        // harperJsUrl is passed via wp_localize_script in class-dashboard.php
        // (using get_harper_url()) so it lands in the spellmatic object without
        // risk of being overwritten by a later var spellmatic = {...} declaration.

        add_filter( 'script_loader_tag', [ __CLASS__, 'add_module_type' ], 10, 2 );
    }

    /**
     * Insert type="module" into the <script> tag for the bridge only.
     */
    public static function add_module_type( string $tag, string $handle ): string {
        if ( 'harper-bridge' === $handle ) {
            $tag = preg_replace( '/(<script\b[^>]*?)(\ssrc=)/', '$1 type="module"$2', $tag, 1 );
        }
        return $tag;
    }

    // ── Privacy policy suggestion ────────────────────────────────────────────
    /**
     * Registers a suggested privacy policy text via the WordPress Privacy API.
     * Hooked to admin_init.
     */
    public static function add_privacy_policy(): void {
        if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) {
            return;
        }

        $content = sprintf(
            '<h2>%s</h2><p>%s</p><p>%s</p>',
            esc_html__( 'Spellmatic', 'spellmatic' ),
            esc_html__( 'This site uses the Spellmatic plugin for spell-checking and grammar correction. By default, all scanning is performed locally in your browser using the Harper open-source grammar engine — no content leaves your server.', 'spellmatic' ),
            esc_html__( 'If the site administrator enables the optional AI-powered scanning feature, post and page text may be sent to a third-party AI provider (such as OpenAI, Anthropic, Google, xAI, or OpenRouter) for additional grammar analysis. This occurs only when the administrator explicitly initiates an AI scan. API keys are stored encrypted on the server and content is transmitted over HTTPS.', 'spellmatic' )
        );

        wp_add_privacy_policy_content( 'Spellmatic', $content );
    }

    /**
     * PHP-side check() — no-op in Phase 2.
     * Scanning is browser-side; this is kept for single-post endpoint compat.
     */
    public static function check( string $text, int $post_id = 0 ): array {
        return [];
    }
}
