<?php
/**
 * Shared mutation logic for admin AJAX and ms-chat agent REST.
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Rank_Ms_Chat_Services {

    /**
     * Initiate health fix processing for a batch or issue type.
     *
     * When issue_type is provided without batch_id, prepares a full batch (same as
     * admin AJAX) and queues server-side auto-approval + Action Scheduler jobs.
     *
     * @param string $batch_id   Existing batch option key.
     * @param string $issue_type Health issue type (e.g. missing_alt_tags).
     * @return array|WP_Error
     */
    public static function health_fix_start( $batch_id = '', $issue_type = '' ) {
        $batch_id   = sanitize_key( (string) $batch_id );
        $issue_type = sanitize_key( (string) $issue_type );

        if ( empty( $batch_id ) && empty( $issue_type ) ) {
            return new WP_Error(
                'missing_params',
                'Provide issue_type to start a new batch, or batch_id to resume one.',
                array( 'status' => 400 )
            );
        }

        if ( empty( $batch_id ) ) {
            $prepared = Rank_Ajax::prepare_health_batch_full( $issue_type );
            if ( is_wp_error( $prepared ) ) {
                return $prepared;
            }

            if ( empty( $prepared['batch_id'] ) || (int) $prepared['count'] === 0 ) {
                return array(
                    'message'           => 'No issues found for this category.',
                    'batch_id'          => null,
                    'issue_type'        => $issue_type,
                    'count'             => 0,
                    'total_count'       => 0,
                    'available_credits' => $prepared['available_credits'] ?? 0,
                    'status'            => 'batch_empty',
                );
            }

            $batch_id = $prepared['batch_id'];
            $filtered = Rank_Ajax::filter_already_fixed_batch_public( $batch_id );
            if ( is_wp_error( $filtered ) ) {
                return $filtered;
            }

            if ( (int) $filtered['fixableTotal'] === 0 ) {
                return array_merge(
                    array(
                        'message'           => 'It seems this was already fixed. Try to do a full health scan. Or ask me to do it 👍️',
                        'batch_id'          => $batch_id,
                        'issue_type'        => $issue_type,
                        'count'             => 0,
                        'total_count'       => (int) $filtered['reportedTotal'],
                        'available_credits' => $prepared['available_credits'] ?? 0,
                        'status'            => 'batch_complete',
                    ),
                    $filtered
                );
            }

            $queued = Rank_Ajax::queue_health_batch_processing( $batch_id );
            if ( is_wp_error( $queued ) ) {
                return $queued;
            }

            return array_merge(
                array(
                    'message'           => 'Batch created and processing started.',
                    'batch_id'          => $batch_id,
                    'issue_type'        => $issue_type,
                    'count'             => (int) $filtered['fixableTotal'],
                    'total_count'       => (int) $filtered['reportedTotal'],
                    'actual_total'      => $prepared['actual_total'],
                    'available_credits' => $prepared['available_credits'] ?? 0,
                    'status'            => 'processing',
                ),
                $filtered
            );
        }

        $batch_validation = Rank_Ajax::validate_batch_id_public( $batch_id );
        if ( is_wp_error( $batch_validation ) ) {
            return $batch_validation;
        }

        $batch_data = get_option( $batch_id );
        if ( ! $batch_data ) {
            return new WP_Error( 'batch_not_found', 'Batch not found.', array( 'status' => 404 ) );
        }

        if ( ! isset( $batch_data['fixable_total'] ) ) {
            $filtered = Rank_Ajax::filter_already_fixed_batch_public( $batch_id );
            if ( is_wp_error( $filtered ) ) {
                return $filtered;
            }

            if ( (int) $filtered['fixableTotal'] === 0 ) {
                return array_merge(
                    array(
                        'message'    => 'It seems this was already fixed. Try to do a full health scan. Or ask me to do it 👍️',
                        'batch_id'   => $batch_id,
                        'issue_type' => $batch_data['issue_type'] ?? '',
                        'status'     => 'batch_complete',
                    ),
                    $filtered
                );
            }
        }

        $queued = Rank_Ajax::queue_health_batch_processing( $batch_id );
        if ( is_wp_error( $queued ) ) {
            return $queued;
        }

        $batch_data = get_option( $batch_id );
        $progress   = is_array( $batch_data ) ? Rank_Ajax::batch_progress_fields( $batch_data ) : array();

        return array_merge(
            array(
                'message'    => 'Processing initiated. Status checks will begin.',
                'batch_id'   => $batch_id,
                'issue_type' => is_array( $batch_data ) ? ( $batch_data['issue_type'] ?? '' ) : '',
                'status'     => 'processing',
            ),
            $progress
        );
    }

    /**
     * Get health fix batch / Action Scheduler state.
     *
     * When batch_id is omitted, returns the current active batch (if any).
     *
     * @param string $batch_id Batch option key.
     * @return array|WP_Error
     */
    public static function health_job_status( $batch_id = '' ) {
        $batch_id = sanitize_key( (string) $batch_id );
        if ( empty( $batch_id ) ) {
            return Rank_Ajax::get_active_health_batch_data();
        }

        return Rank_Ajax::get_health_batch_status_data( $batch_id );
    }

    /**
     * Cancel in-flight health fix processing for a batch.
     *
     * @param string $batch_id Batch option key.
     * @return array|WP_Error
     */
    public static function health_fix_cancel( $batch_id ) {
        return Rank_Ajax::cancel_health_batch_public( $batch_id );
    }

    /**
     * Start a page booster optimization session.
     *
     * @param array $rows Prepared row data.
     * @return array|WP_Error
     */
    public static function booster_start( $rows ) {
        return Rank_Booster_Ajax::start_optimization( $rows );
    }

    /**
     * Get page booster session status.
     *
     * @param string $session_id Session UUID.
     * @return array|WP_Error
     */
    public static function booster_status( $session_id ) {
        return Rank_Booster_Ajax::get_session_status_data( $session_id );
    }

    /**
     * Push booster draft changes live.
     *
     * @param int $job_id Booster job ID.
     * @return array|WP_Error
     */
    public static function booster_push_live( $job_id ) {
        return Rank_Booster_Ajax::push_live_job( $job_id );
    }

    /**
     * Upload Rank Writer articles to WordPress as drafts.
     *
     * @param array $article_ids Article IDs from Morningscore API.
     * @return array|WP_Error
     */
    public static function writer_upload( $article_ids ) {
        if ( empty( $article_ids ) || ! is_array( $article_ids ) ) {
            return new WP_Error( 'missing_articles', 'No articles provided.', array( 'status' => 400 ) );
        }

        $article_ids = array_map( 'sanitize_text_field', $article_ids );

        $results        = array();
        $uploaded_count = 0;
        $failed_count   = 0;

        foreach ( $article_ids as $article_id ) {
            if ( Rank_Writer_DB::is_article_uploaded( $article_id ) ) {
                $results[] = array(
                    'article_id' => $article_id,
                    'status'     => 'skipped',
                    'message'    => 'Already uploaded',
                );
                continue;
            }

            $article = Rank_Writer::get_article( $article_id );

            if ( is_wp_error( $article ) ) {
                $results[] = array(
                    'article_id' => $article_id,
                    'status'     => 'error',
                    'message'    => $article->get_error_message(),
                );
                $failed_count++;
                continue;
            }

            $post_id = Rank_Writer::create_wp_draft( $article );

            if ( is_wp_error( $post_id ) ) {
                $results[] = array(
                    'article_id' => $article_id,
                    'status'     => 'error',
                    'message'    => $post_id->get_error_message(),
                );
                $failed_count++;
                continue;
            }

            $results[] = array(
                'article_id' => $article_id,
                'status'     => 'success',
                'wp_post_id' => $post_id,
                'title'      => $article['title'],
                'edit_url'   => get_edit_post_link( $post_id, 'raw' ),
            );
            $uploaded_count++;
        }

        $message = sprintf( '%d article(s) uploaded as drafts.', $uploaded_count );
        if ( $failed_count > 0 ) {
            $message .= sprintf( ' %d failed.', $failed_count );
        }

        return array(
            'message'  => $message,
            'uploaded' => $uploaded_count,
            'failed'   => $failed_count,
            'results'  => $results,
        );
    }
}
