<?php

declare(strict_types=1);

/**
 * Inclusive Language admin post-list integration (Task 7).
 *
 * - Adds an "Inclusive language = Needs review" filter dropdown.
 * - Caches per-post analysis result in two post-meta keys
 *   (`_prorank_inclusive_lang_hash` + `_prorank_inclusive_lang_total`)
 *   so the column renders fast and the filter can use a plain `meta_query`.
 * - Cache invalidation (save_post + settings-changed bulk flush) lives on
 *   the analyzer's `register_hooks()` boot path, not here, so REST and
 *   editor saves invalidate even when the list table never loads.
 *
 * No content is modified, no external API is called, and all hooks are
 * gated by `current_user_can('edit_posts')` so subscribers do not see it.
 *
 * @package ProRank\SEO\Admin
 * @since 1.3.1
 */

namespace ProRank\SEO\Admin;

use ProRank\SEO\Core\Content\InclusiveLanguageAnalyzer;

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

class InclusiveLanguageColumn {

    private const FILTER_PARAM  = 'prorank_inclusive_filter';
    private const META_TOTAL_KEY = '_prorank_inclusive_lang_total';

    /**
     * Supported post types — defaults to posts + pages, filterable.
     *
     * @var array<int,string>
     */
    private array $post_types;

    public function __construct() {
        $defaults = [ 'post', 'page' ];
        $filtered = function_exists( 'apply_filters' )
            ? apply_filters( 'prorank_inclusive_language_post_types', $defaults )
            : $defaults;
        $this->post_types = array_values( array_unique( array_filter( (array) $filtered, 'is_string' ) ) ) ?: $defaults;
    }

    public function register(): void {
        if ( ! function_exists( 'add_action' ) || ! function_exists( 'add_filter' ) ) {
            return;
        }

        add_action( 'restrict_manage_posts', [ $this, 'render_filter_dropdown' ] );
        add_action( 'pre_get_posts',         [ $this, 'apply_filter_query' ] );
        // `save_post` cache invalidation is registered from the analyzer at
        // plugin boot — admin_init runs too late for REST/editor saves.
    }

    /**
     * Add a "Inclusive language = Needs review" dropdown to the list-table
     * filter row. Limited to supported post types.
     */
    public function render_filter_dropdown( $post_type ): void {
        if ( ! is_string( $post_type ) || ! in_array( $post_type, $this->post_types, true ) ) {
            return;
        }
        if ( ! self::current_user_can_use() ) {
            return;
        }
        if ( ! InclusiveLanguageAnalyzer::get_settings()['enabled'] ) {
            return;
        }
        $current = isset( $_GET[ self::FILTER_PARAM ] )
            ? sanitize_text_field( wp_unslash( (string) $_GET[ self::FILTER_PARAM ] ) )
            : '';
        ?>
        <label for="prorank-inclusive-filter" class="screen-reader-text">
            <?php esc_html_e( 'Filter by inclusive language status', 'prorank-seo' ); ?>
        </label>
        <select name="<?php echo esc_attr( self::FILTER_PARAM ); ?>" id="prorank-inclusive-filter">
            <option value=""><?php esc_html_e( 'Inclusive language: All', 'prorank-seo' ); ?></option>
            <option value="needs_review" <?php selected( $current, 'needs_review' ); ?>>
                <?php esc_html_e( 'Inclusive language: Needs review', 'prorank-seo' ); ?>
            </option>
        </select>
        <?php
    }

    /**
     * Apply the filter to the main list query. Uses a `meta_query` against
     * `_prorank_inclusive_lang_total > 0` so we never load post content
     * during the query; only previously-analyzed posts surface.
     */
    public function apply_filter_query( $query ): void {
        if ( ! function_exists( 'is_admin' ) || ! is_admin() ) {
            return;
        }
        if ( ! $query instanceof \WP_Query || ! $query->is_main_query() ) {
            return;
        }
        $screen_post_type = isset( $_GET['post_type'] ) ? sanitize_key( (string) $_GET['post_type'] ) : 'post';
        if ( ! in_array( $screen_post_type, $this->post_types, true ) ) {
            return;
        }
        $value = isset( $_GET[ self::FILTER_PARAM ] )
            ? sanitize_text_field( wp_unslash( (string) $_GET[ self::FILTER_PARAM ] ) )
            : '';
        if ( $value !== 'needs_review' ) {
            return;
        }
        // When the feature is disabled the meta is bulk-flushed, but a stale
        // bookmark could still send `?prorank_inclusive_filter=needs_review`.
        // Refuse the filter outright so the list cannot be empty-by-design.
        if ( ! InclusiveLanguageAnalyzer::get_settings()['enabled'] ) {
            return;
        }
        $existing = (array) $query->get( 'meta_query' );
        $existing[] = [
            'key'     => self::META_TOTAL_KEY,
            'value'   => 0,
            'compare' => '>',
            'type'    => 'NUMERIC',
        ];
        $query->set( 'meta_query', $existing );
    }

    private static function current_user_can_use(): bool {
        return function_exists( 'current_user_can' ) && current_user_can( 'edit_posts' );
    }
}
