<?php
if (!defined('ABSPATH')) exit;

class AISB_Queue {

    public static function init() {
        add_action('aisb_process_queue', [__CLASS__, 'process']);
    }

    public static function create_job($post_ids, $type = 'bulk_schema') {
        $ids = array_values(array_unique(array_filter(array_map('intval', (array) $post_ids))));
        if (empty($ids)) {
            return new WP_Error('aisb_no_items', __('No posts selected for bulk generation.', 'pewit-ai-schema-builder'));
        }

        $job = [
            'id'          => 'job_' . time() . '_' . wp_rand(1000, 9999),
            'status'      => 'running',
            'type'        => $type,
            'total'       => count($ids),
            'remaining'   => $ids,
            'processed'   => [],
            'failed'      => [],
            'skipped'     => [],
            'log'         => [],
            'current'     => null,
            'started_at'  => current_time('mysql'),
            'started_ts'  => time(),
            'updated_at'  => current_time('mysql'),
            'message'     => __('Job started', 'pewit-ai-schema-builder'),
        ];
        self::add_log($job, 'info', __('Bulk schema job started', 'pewit-ai-schema-builder'), ['total' => count($ids)]);
        update_option(AISB_JOB_OPTION, $job, false);
        if (!wp_next_scheduled('aisb_process_queue')) {
            wp_schedule_single_event(time() + 5, 'aisb_process_queue');
        }
        return $job;
    }

    public static function create_missing_job() {
        $ids = AISB_Schema::posts_without_schema();
        return self::create_job($ids, 'missing_schema');
    }

    public static function get_job() {
        $job = get_option(AISB_JOB_OPTION, null);
        if (!$job || !is_array($job)) {
            return $job;
        }
        $done = count($job['processed'] ?? []) + count($job['failed'] ?? []) + count($job['skipped'] ?? []);
        $total = (int) ($job['total'] ?? 0);
        $remaining = max(0, $total - $done);
        $job['done'] = $done;
        $job['remaining_count'] = $remaining;
        if ($remaining > 0 && $done >= 3) {
            $elapsed = max(1, time() - (int) ($job['started_ts'] ?? time()));
            $avg = $elapsed / max(1, $done);
            $job['eta_seconds'] = (int) round($avg * $remaining);
            $job['eta_text'] = self::format_seconds($job['eta_seconds']);
        }
        return $job;
    }

    public static function save_job($job) {
        $job['updated_at'] = current_time('mysql');
        update_option(AISB_JOB_OPTION, $job, false);
    }

    public static function pause() {
        $job = self::get_job();
        if ($job) {
            $job['status'] = 'paused';
            $job['message'] = __('Paused', 'pewit-ai-schema-builder');
            self::add_log($job, 'warning', __('Job paused', 'pewit-ai-schema-builder'));
            self::save_job($job);
        }
        return $job;
    }

    public static function resume() {
        $job = self::get_job();
        if ($job) {
            $job['status'] = 'running';
            $job['message'] = __('Resumed', 'pewit-ai-schema-builder');
            self::add_log($job, 'info', __('Job resumed', 'pewit-ai-schema-builder'));
            self::save_job($job);
            wp_schedule_single_event(time() + 2, 'aisb_process_queue');
        }
        return $job;
    }

    public static function stop() {
        $job = self::get_job();
        if ($job) {
            $job['status'] = 'stopped';
            $job['message'] = __('Stopped by user', 'pewit-ai-schema-builder');
            $job['stopped_ts'] = time();
            self::add_log($job, 'warning', __('Job stopped by user', 'pewit-ai-schema-builder'));
            self::save_job($job);
        }
        return $job;
    }

    public static function clear() {
        delete_option(AISB_JOB_OPTION);
    }

    public static function process() {
        $job = self::get_job();
        if (!$job || ($job['status'] ?? '') !== 'running') {
            return;
        }
        if (!aisb_api_ready()) {
            $job['status'] = 'stopped';
            $job['message'] = __('Stopped: API key not ready.', 'pewit-ai-schema-builder');
            self::add_log($job, 'error', $job['message']);
            self::save_job($job);
            return;
        }

        $settings = aisb_get_settings();
        $batch = max(1, min(10, (int) ($settings['batch_size'] ?? 3)));
        $remaining = array_splice($job['remaining'], 0, $batch);

        foreach ($remaining as $post_id) {
            if (($job['status'] ?? '') !== 'running') {
                break;
            }
            $post = get_post($post_id);
            if (!$post || $post->post_status !== 'publish') {
                $job['skipped'][] = ['id' => $post_id, 'reason' => __('Not published', 'pewit-ai-schema-builder')];
                self::add_log($job, 'warning', sprintf(/* translators: %d are replaced with dynamic values */ __('Skipped post %d — not published', 'pewit-ai-schema-builder'), $post_id));
                continue;
            }
            if (AISB_Schema::get_json($post_id) && ($job['type'] ?? '') !== 'score_boost') {
                $job['skipped'][] = ['id' => $post_id, 'reason' => __('Schema already exists', 'pewit-ai-schema-builder')];
                self::add_log($job, 'warning', sprintf(/* translators: %d are replaced with dynamic values */ __('Skipped post %d — schema exists', 'pewit-ai-schema-builder'), $post_id));
                continue;
            }

            $job['current'] = ['id' => $post_id, 'title' => get_the_title($post_id)];
            self::save_job($job);

            $type = AISB_Schema::detect_type($post);
            $result = AISB_API::generate_schema($post_id, $type);
            if (is_wp_error($result)) {
                $job['failed'][] = ['id' => $post_id, 'error' => $result->get_error_message()];
                self::add_log($job, 'error', sprintf(/* translators: 1: post ID, 2: error message */ __('Failed post %1$d: %2$s', 'pewit-ai-schema-builder'), $post_id, $result->get_error_message()));
            } else {
                AISB_Schema::save($post_id, $result, $type);
                $job['processed'][] = ['id' => $post_id, 'type' => $type];
                $log_msg = ($job['type'] ?? '') === 'score_boost'
                    ? sprintf(/* translators: 1: post ID, 2: schema type */ __('Boosted schema for post %1$d (%2$s)', 'pewit-ai-schema-builder'), $post_id, $type)
                    : sprintf(/* translators: 1: post ID, 2: schema type */ __('Generated schema for post %1$d (%2$s)', 'pewit-ai-schema-builder'), $post_id, $type);
                self::add_log($job, 'success', $log_msg);
            }
            self::save_job($job);
        }

        if (empty($job['remaining'])) {
            $job['status'] = 'completed';
            $job['message'] = __('Completed', 'pewit-ai-schema-builder');
            $job['completed_ts'] = time();
            $job['current'] = null;
            self::add_log($job, 'success', __('Job completed', 'pewit-ai-schema-builder'));
            self::save_job($job);
            AISB_Job_Notify::maybe_send($job);
            return;
        }

        self::save_job($job);
        $delay = max(2, min(60, (int) ($settings['batch_delay'] ?? 5)));
        wp_schedule_single_event(time() + $delay, 'aisb_process_queue');
    }

    private static function add_log(&$job, $level, $message, $data = []) {
        if (empty($job['log']) || !is_array($job['log'])) {
            $job['log'] = [];
        }
        $job['log'][] = [
            'ts'      => time(),
            'time'    => current_time('H:i:s'),
            'level'   => sanitize_key($level),
            'message' => wp_strip_all_tags((string) $message),
            'data'    => is_array($data) ? $data : [],
        ];
        if (count($job['log']) > 200) {
            $job['log'] = array_slice($job['log'], -200);
        }
    }

    private static function format_seconds($seconds) {
        $seconds = max(0, (int) $seconds);
        $m = floor($seconds / 60);
        $s = $seconds % 60;
        if ($m > 0) {
            return $m . 'm ' . $s . 's';
        }
        return $s . 's';
    }
}
