<?php
/**
 * AI-Visibility Tracker AJAX handlers (admin-only: manual check + prompt editing).
 *
 * @package    SiteStaffr
 * @subpackage SiteStaffr/admin/traits
 * @since      1.36.0
 */

if ( ! defined( 'WPINC' ) ) {
    die;
}

trait SiteStaffr_Admin_Visibility_Ajax_Trait {

    /**
     * Run an on-demand ("Check now") visibility check.
     *
     * No email is sent on this path — email delivery is monthly-cron only
     * (see SiteStaffr_Visibility::run_tick()).
     *
     * @since 1.36.0
     */
    public function ajax_visibility_check_now() {
        if ( ! check_ajax_referer( 'sitestaffr_visibility', 'nonce', false ) ) {
            wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
            return;
        }

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => __( 'Unauthorized.', 'sitestaffr' ) ) );
            return;
        }

        $run = SiteStaffr_Visibility::request_run( 'manual' );

        if ( is_wp_error( $run ) ) {
            $code = $run->get_error_code();

            if ( 'rate_limited' === $code ) {
                $error_data = $run->get_error_data();
                $resets_at  = ( is_array( $error_data ) && isset( $error_data['resets_at'] ) ) ? $error_data['resets_at'] : '';
                $message    = __( "You've used this month's on-demand visibility checks.", 'sitestaffr' );
                if ( '' !== $resets_at ) {
                    $message .= ' ' . sprintf(
                        /* translators: %s: date/time the rate limit resets. */
                        __( 'Resets %s.', 'sitestaffr' ),
                        $resets_at
                    );
                }
                wp_send_json_error( array( 'message' => $message, 'code' => $code ) );
                return;
            }

            if ( 'not_entitled' === $code ) {
                wp_send_json_error( array(
                    'message' => __( 'Visibility checks aren\'t available on your current plan. Upgrade to unlock this feature.', 'sitestaffr' ),
                    'code'    => $code,
                ) );
                return;
            }

            wp_send_json_error( array(
                'message' => $run->get_error_message() ? $run->get_error_message() : __( 'Visibility check failed. Please try again.', 'sitestaffr' ),
                'code'    => $code,
            ) );
            return;
        }

        SiteStaffr_Visibility::record_run( $run );

        wp_send_json_success( array(
            'run'        => $run,
            'rate_limit' => isset( $run['rate_limit'] ) ? $run['rate_limit'] : null,
        ) );
    }

    /**
     * Email the most recent visibility report on demand.
     *
     * Sends the already-stored `latest` run (the report the owner is looking
     * at) through the same SendGrid pipeline the monthly cron uses — no new
     * check is run and no rate-limit slot is consumed. Lets owners pull their
     * report to their inbox any time instead of waiting for the monthly tick.
     *
     * @since 1.36.0
     */
    public function ajax_visibility_send_report() {
        if ( ! check_ajax_referer( 'sitestaffr_visibility', 'nonce', false ) ) {
            wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
            return;
        }

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => __( 'Unauthorized.', 'sitestaffr' ) ) );
            return;
        }

        $state  = SiteStaffr_Visibility::get_state();
        $latest = ( isset( $state['latest'] ) && is_array( $state['latest'] ) ) ? $state['latest'] : null;

        if ( empty( $latest ) ) {
            wp_send_json_error( array( 'message' => __( 'Run a visibility check first, then email the report.', 'sitestaffr' ) ) );
            return;
        }

        if ( ! class_exists( 'SiteStaffr_Email_Notifications' ) ) {
            wp_send_json_error( array( 'message' => __( 'Could not send the report. Please try again.', 'sitestaffr' ) ) );
            return;
        }

        $notifier = new SiteStaffr_Email_Notifications();
        $sent     = $notifier->send_visibility_report( $latest );

        if ( ! $sent ) {
            wp_send_json_error( array( 'message' => __( 'Could not send the report. Check that a notification email is set, then try again.', 'sitestaffr' ) ) );
            return;
        }

        wp_send_json_success();
    }

    /**
     * Ask the middleware for fresh prompt suggestions that target the site's
     * visibility gaps. Returns candidates for the owner to review and add — it
     * does NOT save anything (the owner adds the ones they want, then Saves the
     * prompt list as usual).
     *
     * @since 1.36.2
     */
    public function ajax_visibility_suggest_prompts() {
        if ( ! check_ajax_referer( 'sitestaffr_visibility', 'nonce', false ) ) {
            wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
            return;
        }

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => __( 'Unauthorized.', 'sitestaffr' ) ) );
            return;
        }

        $suggestions = SiteStaffr_Visibility::suggest_prompts();

        if ( is_wp_error( $suggestions ) ) {
            wp_send_json_error( array(
                'message' => $suggestions->get_error_message() ? $suggestions->get_error_message() : __( "Couldn't get suggestions. Please try again.", 'sitestaffr' ),
            ) );
            return;
        }

        wp_send_json_success( array( 'prompts' => array_values( (array) $suggestions ) ) );
    }

    /**
     * Save an edited prompt list (owner-authored prompts replace the seeded
     * set) and reschedule the monthly tick so the change takes effect
     * without waiting out a stale schedule.
     *
     * @since 1.36.0
     */
    public function ajax_visibility_update_prompts() {
        if ( ! check_ajax_referer( 'sitestaffr_visibility', 'nonce', false ) ) {
            wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
            return;
        }

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => __( 'Unauthorized.', 'sitestaffr' ) ) );
            return;
        }

        $raw_prompts = ( isset( $_POST['prompts'] ) && is_array( $_POST['prompts'] ) )
            ? wp_unslash( $_POST['prompts'] )
            : array();

        $allowed_types = array( 'branded', 'unbranded' );
        $sanitized     = array();

        foreach ( $raw_prompts as $raw_prompt ) {
            if ( ! is_array( $raw_prompt ) ) {
                continue;
            }

            $text = isset( $raw_prompt['text'] ) ? sanitize_text_field( $raw_prompt['text'] ) : '';
            if ( '' === $text ) {
                continue;
            }

            $type = isset( $raw_prompt['type'] ) ? sanitize_key( $raw_prompt['type'] ) : '';
            if ( ! in_array( $type, $allowed_types, true ) ) {
                $type = 'branded';
            }

            $id = isset( $raw_prompt['id'] ) ? sanitize_text_field( $raw_prompt['id'] ) : '';
            if ( '' === $id ) {
                $id = uniqid( 'vp_', true );
            }

            $sanitized[] = array(
                'id'   => $id,
                'text' => $text,
                'type' => $type,
            );

            if ( count( $sanitized ) >= SiteStaffr_Visibility::MAX_PROMPTS ) {
                break;
            }
        }

        $state             = SiteStaffr_Visibility::get_state();
        $state['prompts']  = $sanitized;
        SiteStaffr_Visibility::save_state( $state );

        // A prompt change should not wait out a stale schedule — reschedule
        // the monthly tick now (closes the Task 13 TODO(B4)).
        SiteStaffr_Visibility::reschedule();

        wp_send_json_success( array( 'prompts' => $sanitized ) );
    }

}
