<?php

namespace XZD\AI\V5\SEO;

/**
 * DeadLinkMonitor — 异步死链监控
 *
 * 分批扫描文章中的外部链接，异步执行避免超时
 * 结果缓存24小时，检测到死链可设置301重定向
 *
 * @since V3.2.0
 */
class DeadLinkMonitor
{
    const RESULT_OPTION = 'xzd_deadlink_results';
    const SCAN_LOCK = 'xzd_deadlink_scan_lock';

    /**
     * 分批扫描（每批10篇文章，异步WP-Cron调度）
     */
    public function startScan(int $batchSize = 10): array
    {
        if (get_transient(self::SCAN_LOCK)) {
            return ['success' => false, 'message' => '扫描正在进行中，请稍后再试'];
        }
        set_transient(self::SCAN_LOCK, time(), 300);

        // 调度异步扫描
        as_schedule_single_action(time() + 5, 'xzd_deadlink_scan_batch', ['offset' => 0, 'batch' => $batchSize]);

        return ['success' => true, 'message' => '死链扫描已启动，将在后台异步执行'];
    }

    /**
     * 扫描一批文章（由AS回调）
     */
    public function scanBatch(int $offset, int $batchSize): array
    {
        $posts = get_posts([
            'post_type'      => 'post',
            'post_status'    => 'publish',
            'posts_per_page' => $batchSize,
            'offset'         => $offset,
            'orderby'        => 'ID',
            'order'          => 'DESC',
        ]);

        if (empty($posts)) {
            delete_transient(self::SCAN_LOCK);
            return ['done' => true, 'offset' => $offset];
        }

        $results = get_option(self::RESULT_OPTION, []);
        $checked = 0;

        foreach ($posts as $post) {
            // 每篇文章最多检测5个外链
            preg_match_all('/href=["\'](https?:\/\/[^"\']+)["\']/i', $post->post_content, $matches);
            $urls = array_slice(array_unique($matches[1]), 0, 5);

            foreach ($urls as $url) {
                // 跳过本站链接
                if (strpos($url, home_url()) === 0) continue;

                // 缓存检查（24小时内同一URL不重复检测）
                $cacheKey = 'xzd_dl_' . md5($url);
                $cached = get_transient($cacheKey);
                if ($cached !== false) {
                    if ($cached['dead']) {
                        $results[$url] = $cached;
                    }
                    continue;
                }

                $resp = wp_remote_head($url, ['timeout' => 5]);
                $code = is_wp_error($resp) ? 0 : wp_remote_retrieve_response_code($resp);
                $dead = ($code >= 400 || $code === 0);

                $entry = ['url' => $url, 'post_id' => $post->ID, 'post_title' => $post->post_title, 'code' => $code, 'checked_at' => current_time('mysql')];
                set_transient($cacheKey, $entry + ['dead' => $dead], DAY_IN_SECONDS);

                if ($dead) {
                    $results[$url] = $entry;
                }
                $checked++;
            }
        }

        update_option(self::RESULT_OPTION, $results, false);

        // 继续下一批
        if (count($posts) === $batchSize) {
            as_schedule_single_action(time() + 10, 'xzd_deadlink_scan_batch', [
                'offset' => $offset + $batchSize,
                'batch'  => $batchSize,
            ]);
            return ['done' => false, 'offset' => $offset + $batchSize, 'found' => count($results)];
        }

        delete_transient(self::SCAN_LOCK);
        return ['done' => true, 'total_checked' => $offset + count($posts), 'dead_links' => count($results)];
    }

    /**
     * 获取扫描结果
     */
    public function getResults(): array
    {
        return get_option(self::RESULT_OPTION, []);
    }

    /**
     * 清除扫描结果
     */
    public function clearResults(): void
    {
        delete_option(self::RESULT_OPTION);
    }
}
