<?php

declare(strict_types=1);

namespace ProRank\SEO\CLI;

use ProRank\SEO\Core\Content\TitleAuditor;
use WP_CLI;

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

/**
 * Title-too-long detection (Phase 1 — read only, no fixes).
 *
 * ## EXAMPLES
 *
 *     wp prorank titles scan --too-long
 *     wp prorank titles scan --too-long --verify
 *     wp prorank titles scan --too-long --verify --limit=500 --format=json
 */
class TitlesCommand {

    /**
     * Scan content for too-long titles.
     *
     * ## OPTIONS
     *
     * [--too-long]
     * : Filter to the title-too-long issue (the only issue in Phase 1).
     *
     * [--verify]
     * : Run the cache-safe live <title> pass and report confirmed buckets.
     *
     * [--limit=<n>]
     * : With --verify, max pages to fetch. Default 500, cap 500.
     *
     * [--format=<format>]
     * : table|json. Default table.
     *
     * @when after_wp_load
     */
    public function scan( $args, $assoc_args ): void {
        $auditor = new TitleAuditor();
        $json = ( $assoc_args['format'] ?? 'table' ) === 'json';

        if ( isset( $assoc_args['verify'] ) ) {
            $limit = max( 1, min( 500, (int) ( $assoc_args['limit'] ?? 500 ) ) );
            $v = $auditor->verify( $limit );
            if ( $json ) {
                WP_CLI::log( (string) wp_json_encode( $v ) );
                return;
            }
            $b = $v['buckets'];
            $complete = ! empty( $b['complete'] );
            WP_CLI::log( 'Scanned                    : ' . (int) $v['total_scanned'] );
            WP_CLI::log( 'Title limit                : ' . (int) $v['limit'] );
            WP_CLI::log( 'Stored too-long (candidates): ' . (int) $b['stored_too_long'] );
            WP_CLI::log( 'Live-verified examined     : ' . (int) $b['examined'] );
            WP_CLI::log( 'Not yet verified           : ' . (int) $b['unverified_remaining'] . ( $complete ? '' : ' (raise --limit)' ) );
            WP_CLI::log( ( $complete ? 'CONFIRMED too long         : ' : 'Confirmed too long (so far): ' ) . (int) $b['too_long_confirmed'] . ( $complete ? ' (full-site real number)' : ' — LOWER BOUND' ) );
            WP_CLI::log( '  └ needs shorter SEO title : ' . (int) $b['needs_rewrite'] );
            WP_CLI::log( 'OK once rendered           : ' . (int) $b['ok_rendered'] );
            WP_CLI::log( 'Auto-handled (sitename omit): ' . (int) $b['mechanically_ok_after_sitename_omit'] . ' (already <=limit live — not a problem)' );
            WP_CLI::log( 'Inconclusive (skipped)     : ' . (int) $b['inconclusive'] );

            $confirmed = array_values( array_filter( $v['items'], static fn( $i ) => $i['verification'] === 'too_long_confirmed' ) );
            if ( empty( $confirmed ) ) {
                WP_CLI::success( 'No CONFIRMED too-long titles.' );
                return;
            }
            $rows = [];
            foreach ( array_slice( $confirmed, 0, 100 ) as $m ) {
                $rows[] = [
                    'id'        => (int) $m['id'],
                    'rendered'  => (string) ( $m['rendered_title'] ?? '' ),
                    'len'       => (int) ( $m['rendered_len'] ?? 0 ),
                    'status'    => (string) $m['status'],
                    'override'  => ! empty( $m['manual_override'] ) ? 'yes' : 'no',
                ];
            }
            WP_CLI\Utils\format_items( 'table', $rows, [ 'id', 'rendered', 'len', 'status', 'override' ] );
            return;
        }

        $scan = $auditor->scan();
        if ( $json ) {
            WP_CLI::log( (string) wp_json_encode( $scan ) );
            return;
        }
        WP_CLI::log( 'Scanned                : ' . (int) $scan['total_scanned'] );
        WP_CLI::log( 'Title limit            : ' . (int) $scan['limit'] );
        WP_CLI::log( 'Stored too-long        : ' . (int) $scan['stored_too_long'] . ' (needs shorter SEO title; run --verify for the real, rendered number)' );
        WP_CLI::log( 'Auto-handled (sitename): ' . (int) $scan['mechanically_ok_after_sitename_omit_count'] . ' (over only because of sitename suffix — already stripped at render time, not a problem)' );

        if ( empty( $scan['items'] ) ) {
            WP_CLI::success( 'No stored too-long titles.' );
            return;
        }
        $rows = [];
        foreach ( array_slice( $scan['items'], 0, 100 ) as $m ) {
            $rows[] = [
                'id'        => (int) $m['id'],
                'title'     => (string) $m['title'],
                'type'      => (string) $m['type'],
                'eff_len'   => (int) $m['effective_len'],
                'proj_len'  => (int) $m['projected_len'],
                'status'    => (string) $m['status'],
            ];
        }
        WP_CLI\Utils\format_items( 'table', $rows, [ 'id', 'title', 'type', 'eff_len', 'proj_len', 'status' ] );
    }

    /**
     * Show the deterministic suggested SEO title for a post (read only).
     *
     * ## OPTIONS
     *
     * --post_id=<id>
     * : The post to inspect.
     *
     * @when after_wp_load
     */
    public function suggest( $args, $assoc_args ): void {
        $post_id = (int) ( $assoc_args['post_id'] ?? 0 );
        if ( $post_id <= 0 || ! get_post( $post_id ) ) {
            WP_CLI::error( 'A valid --post_id is required.' );
            return;
        }
        $s = ( new \ProRank\SEO\Core\Content\TitleRewriter() )->suggest( $post_id );
        WP_CLI::log( 'Post           : ' . $post_id );
        WP_CLI::log( 'Source         : ' . (string) $s['source'] );
        WP_CLI::log( 'Current title  : ' . (string) $s['current_title'] . ' (' . (int) $s['current_len'] . ')' );
        WP_CLI::log( 'Suggested title: ' . (string) $s['suggested_title'] . ' (' . (int) $s['suggested_len'] . ')' );
        WP_CLI::log( 'Method         : ' . (string) $s['method'] );
        WP_CLI::log( 'Within limit   : ' . ( ! empty( $s['within_limit'] ) ? 'yes' : 'NO' ) );
    }

    /**
     * Apply an explicit SEO title to ONE post. Writes only _prorank_seo_title.
     *
     * ## OPTIONS
     *
     * --post_id=<id>
     * : The post to update.
     *
     * [--title=<title>]
     * : Title to save. If omitted, the deterministic suggestion is used.
     *
     * [--commit]
     * : Actually write. Without this the command is a dry run.
     *
     * @when after_wp_load
     */
    public function apply( $args, $assoc_args ): void {
        $post_id = (int) ( $assoc_args['post_id'] ?? 0 );
        if ( $post_id <= 0 || ! get_post( $post_id ) ) {
            WP_CLI::error( 'A valid --post_id is required.' );
            return;
        }
        $rewriter = new \ProRank\SEO\Core\Content\TitleRewriter();
        $title = isset( $assoc_args['title'] ) ? (string) $assoc_args['title'] : '';
        if ( $title === '' ) {
            $s = $rewriter->suggest( $post_id );
            $title = (string) $s['suggested_title'];
            WP_CLI::log( 'Using deterministic suggestion: ' . $title );
        }
        $dry_run = ! isset( $assoc_args['commit'] );
        $r = $rewriter->apply( $post_id, $title, $dry_run );
        WP_CLI::log( 'Mode    : ' . ( $dry_run ? 'DRY RUN' : 'COMMIT' ) );
        WP_CLI::log( 'Reason  : ' . (string) ( $r['reason'] ?? '' ) );
        if ( ! empty( $r['mutated'] ) ) {
            WP_CLI::success( 'Saved _prorank_seo_title (a restorable backup was kept).' );
        } elseif ( $dry_run && ( $r['reason'] ?? '' ) === 'dry_run' ) {
            WP_CLI::success( 'Would save: "' . (string) $r['seo_title'] . '" — re-run with --commit.' );
        } else {
            WP_CLI::warning( 'No change: ' . (string) ( $r['reason'] ?? '' ) );
        }
    }

    /**
     * Restore the pre-apply SEO title backup for a post.
     *
     * ## OPTIONS
     *
     * --post_id=<id>
     * : The post to restore.
     *
     * [--commit]
     * : Actually restore. Without this the command is a dry run.
     *
     * @when after_wp_load
     */
    public function restore( $args, $assoc_args ): void {
        $post_id = (int) ( $assoc_args['post_id'] ?? 0 );
        if ( $post_id <= 0 || ! get_post( $post_id ) ) {
            WP_CLI::error( 'A valid --post_id is required.' );
            return;
        }
        $dry_run = ! isset( $assoc_args['commit'] );
        $r = ( new \ProRank\SEO\Core\Content\TitleRewriter() )->restore( $post_id, $dry_run );
        if ( ( $r['reason'] ?? '' ) === 'no_backup' ) {
            WP_CLI::error( 'No restorable backup exists for post ' . $post_id . '.' );
            return;
        }
        WP_CLI::log( 'Backup from: ' . (string) ( $r['backed_up_at'] ?? '?' ) );
        WP_CLI::success( $dry_run ? 'Backup exists — re-run with --commit to restore.' : 'SEO title restored from backup.' );
    }

    /**
     * Preview deterministic suggestions for ALL too-long titles.
     *
     * P0 is preview only — this NEVER writes. Apply per title with `apply`.
     *
     * ## OPTIONS
     *
     * [--limit=<n>]
     * : Max candidates to preview. Default 200, cap 500.
     *
     * [--format=<format>]
     * : table|json. Default table.
     *
     * @subcommand repair-all
     * @when after_wp_load
     */
    public function repair_all( $args, $assoc_args ): void {
        $limit = max( 1, min( 500, (int) ( $assoc_args['limit'] ?? 200 ) ) );
        $p = ( new \ProRank\SEO\Core\Content\TitleRewriter() )->repair_all_preview( $limit );
        if ( ( $assoc_args['format'] ?? 'table' ) === 'json' ) {
            WP_CLI::log( (string) wp_json_encode( $p ) );
            return;
        }
        WP_CLI::log( 'PREVIEW ONLY — no titles were written. Apply per title with: wp prorank titles apply --post_id=ID --commit' );
        WP_CLI::log( 'Examined: ' . (int) $p['examined'] );
        $rows = [];
        foreach ( $p['items'] as $m ) {
            $rows[] = [
                'id'        => (int) $m['id'],
                'current'   => (string) $m['current_title'] . ' (' . (int) $m['current_len'] . ')',
                'suggested' => (string) $m['suggested_title'] . ' (' . (int) $m['suggested_len'] . ')',
                'method'    => (string) $m['method'],
                'ok'        => ! empty( $m['within_limit'] ) ? 'yes' : 'NO',
            ];
        }
        WP_CLI\Utils\format_items( 'table', $rows, [ 'id', 'current', 'suggested', 'method', 'ok' ] );
    }
}

if ( defined( 'WP_CLI' ) && WP_CLI ) {
    WP_CLI::add_command( 'prorank titles', 'ProRank\\SEO\\CLI\\TitlesCommand' );
}
