<?php
/**
 * Filter controls for the admin post list translations UI.
 *
 * @package WPR_Translate
 */

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

/**
 * Outputs the admin post list language filter dropdown.
 *
 * @param string $post_type Current post type slug.
 */
function wpr_translation_render_language_filter_control( $post_type ) {
    if ( empty( $post_type ) || 'attachment' === $post_type ) {
        // Skip attachments and invalid post types.
        return;
    }

    $languages = wpr_translation_get_active_languages();

    if ( empty( $languages ) ) {
        return;
    }

    $current_language = isset( $_GET['wpr_language'] ) ? sanitize_text_field( wp_unslash( $_GET['wpr_language'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended

    echo '<label class="screen-reader-text" for="wpr_language">' . esc_html__( 'Filter by language', 'wpr-translate' ) . '</label>';
    echo '<select name="wpr_language" id="wpr_language" class="postform">';
    echo '<option value="">' . esc_html__( 'All languages', 'wpr-translate' ) . '</option>';

    foreach ( $languages as $language ) {
        $code  = $language['code'];
        $label = ! empty( $language['name'] ) ? $language['name'] : strtoupper( $code );

        printf(
            '<option value="%1$s" %2$s>%3$s</option>',
            esc_attr( $code ),
            selected( $current_language, $code, false ),
            esc_html( $label )
        );
    }

    echo '</select>';
}

/**
 * Adds language filter links to the post list subsubsub navigation.
 *
 * @param array $views Existing view links.
 *
 * @return array
 */
function wpr_translation_register_language_views( $views ) {
    global $typenow, $wpdb;

    if ( empty( $typenow ) || 'attachment' === $typenow ) {
        // Skip attachments or missing post type.
        return $views;
    }

    $languages = wpr_translation_get_active_languages();

    if ( empty( $languages ) ) {
        // No languages configured.
        return $views;
    }

    $language_map = array();

    foreach ( $languages as $language ) {
        $code = isset( $language['code'] ) ? sanitize_key( $language['code'] ) : '';
        if ( '' === $code ) {
            continue;
        }
        $slug = isset( $language['slug'] ) ? sanitize_key( $language['slug'] ) : '';
        $codes = array( $code );
        if ( '' !== $slug && $slug !== $code ) {
            $codes[] = $slug;
        }
        $language_map[ $code ] = $codes;
    }

    $current_language = isset( $_GET['wpr_language'] ) ? sanitize_text_field( wp_unslash( $_GET['wpr_language'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended

    $element_type = wpr_translation_get_element_type( $typenow );
    $table        = $wpdb->prefix . 'wpestate_translation_translations';
    $posts_table  = $wpdb->posts;
    $status_filter = isset( $_GET['post_status'] ) ? sanitize_key( wp_unslash( $_GET['post_status'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    $status_clause = "p.post_status NOT IN ('trash','auto-draft')";
    $status_args   = array();

    // Align counts with the current post status filter when provided.
    if ( '' !== $status_filter && 'all' !== $status_filter ) {
        $status_clause = 'p.post_status = %s';
        $status_args   = array( $status_filter );
    }

    $counts_map  = array();
    $default_code = sanitize_key( wpr_translation_get_default_language_code( $languages ) );

    foreach ( $languages as $language ) {
        $code = isset( $language['code'] ) ? sanitize_key( $language['code'] ) : '';
        if ( '' === $code ) {
            continue;
        }

        $codes_to_match = isset( $language_map[ $code ] ) ? $language_map[ $code ] : array( $code );
        $count          = 0;

        if ( $default_code && $code === $default_code ) {
            $placeholders = implode( ', ', array_fill( 0, count( $codes_to_match ), '%s' ) );
            $values       = array_merge( array( $element_type, $typenow ), $status_args, $codes_to_match );

            $count = (int) $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT COUNT(DISTINCT p.ID)
                    FROM {$posts_table} AS p
                    LEFT JOIN {$table} AS t
                        ON p.ID = t.element_id
                        AND t.element_type = %s
                    WHERE p.post_type = %s
                        AND {$status_clause}
                        AND (t.element_id IS NULL OR t.language_code IN ({$placeholders}))",
                    $values
                )
            );
        } elseif ( ! empty( $codes_to_match ) ) {
            $placeholders = implode( ', ', array_fill( 0, count( $codes_to_match ), '%s' ) );
            $values       = array_merge( array( $element_type, $typenow ), $status_args, $codes_to_match );

            $count = (int) $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT COUNT(DISTINCT t.element_id)
                    FROM {$table} AS t
                    INNER JOIN {$posts_table} AS p ON p.ID = t.element_id
                    WHERE t.element_type = %s
                        AND p.post_type = %s
                        AND {$status_clause}
                        AND t.language_code IN ({$placeholders})",
                    $values
                )
            );
        }

        $counts_map[ $code ] = $count;
    }

    if ( '' !== $current_language ) {
        // Clear the "current" class so we can mark the active language view.
        foreach ( $views as $key => $link ) {
            if ( false !== strpos( $link, 'class="current"' ) ) {
                $views[ $key ] = str_replace( 'class="current"', '', $link );
            } elseif ( false !== strpos( $link, "class='current'" ) ) {
                $views[ $key ] = str_replace( "class='current'", '', $link );
            }
        }
    }

    // Build a base URL without language paging.
    $base_url = remove_query_arg( array( 'wpr_language', 'paged', 'post_status' ) );

    foreach ( $languages as $language ) {
        $code = isset( $language['code'] ) ? $language['code'] : '';

        if ( '' === $code ) {
            // Skip invalid language entries.
            continue;
        }

        $label = ! empty( $language['name'] ) ? $language['name'] : strtoupper( $code );
        $count = isset( $counts_map[ $code ] ) ? (int) $counts_map[ $code ] : 0;
        $url   = add_query_arg( 'wpr_language', $code, $base_url );

        $views[ 'wpr_language_' . $code ] = sprintf(
            '<a href="%1$s"%2$s>%3$s <span class="count">(%4$s)</span></a>',
            esc_url( $url ),
            $current_language === $code ? ' class="current"' : '',
            esc_html( $label ),
            esc_html( number_format_i18n( $count ) )
        );
    }

    return $views;
}

/**
 * Filters the main admin query by the selected language.
 *
 * @param WP_Query $query Current query instance.
 */
function wpr_translation_filter_admin_query_by_language( $query ) {
    if ( ! is_admin() || ! $query->is_main_query() ) {
        // Only filter the main admin query.
        return;
    }

    global $pagenow;

    if ( 'edit.php' !== $pagenow ) {
        // Only apply to the post list screen.
        return;
    }

    $selected_language = isset( $_GET['wpr_language'] ) ? sanitize_text_field( wp_unslash( $_GET['wpr_language'] ) ) : '';// phpcs:ignore WordPress.Security.NonceVerification.Recommended

    if ( '' === $selected_language ) {
        // No language filter selected.
        return;
    }

    $languages = wpr_translation_get_active_languages();
    if ( empty( $languages ) ) {
        // No active languages configured.
        return;
    }

    $language_codes = wp_list_pluck( $languages, 'code' );

    if ( ! in_array( $selected_language, $language_codes, true ) ) {
        // Ignore unknown language codes.
        return;
    }

    $post_type = $query->get( 'post_type' );

    if ( is_array( $post_type ) ) {
        $post_type = reset( $post_type );
    }

    if ( empty( $post_type ) || 'attachment' === $post_type ) {
        // Skip invalid or attachment post types.
        return;
    }

    $element_type = wpr_translation_get_element_type( $post_type );

    global $wpdb;

    $table = $wpdb->prefix . 'wpestate_translation_translations';

    $default_code = sanitize_key( wpr_translation_get_default_language_code( $languages ) );
    $language_map = array();

    foreach ( $languages as $language ) {
        $code = isset( $language['code'] ) ? sanitize_key( $language['code'] ) : '';
        if ( '' === $code ) {
            continue;
        }
        $slug = isset( $language['slug'] ) ? sanitize_key( $language['slug'] ) : '';
        $codes = array( $code );
        if ( '' !== $slug && $slug !== $code ) {
            $codes[] = $slug;
        }
        $language_map[ $code ] = $codes;
    }
    $status_filter = isset( $_GET['post_status'] ) ? sanitize_key( wp_unslash( $_GET['post_status'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    $status_clause = "p.post_status NOT IN ('trash','auto-draft')";
    $status_args   = array();

    // Respect the current status view when present.
    if ( '' !== $status_filter && 'all' !== $status_filter ) {
        $status_clause = 'p.post_status = %s';
        $status_args   = array( $status_filter );
    }

    $codes_to_match = isset( $language_map[ $selected_language ] ) ? $language_map[ $selected_language ] : array( $selected_language );

    if ( $default_code && $selected_language === $default_code ) {
        // Include source posts without translation records alongside default-language entries.
        $placeholders = implode( ', ', array_fill( 0, count( $codes_to_match ), '%s' ) );
        $values       = array_merge( array( $element_type, $post_type ), $status_args, $codes_to_match );

        $post_ids = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT DISTINCT p.ID
                FROM {$wpdb->posts} AS p
                LEFT JOIN {$table} AS t
                    ON p.ID = t.element_id
                    AND t.element_type = %s
                WHERE p.post_type = %s
                    AND {$status_clause}
                    AND (t.element_id IS NULL OR t.language_code IN ({$placeholders}))",
                $values
            )
        );
    } elseif ( ! empty( $codes_to_match ) ) {
        $placeholders = implode( ', ', array_fill( 0, count( $codes_to_match ), '%s' ) );
        $values       = array_merge( array( $element_type, $post_type ), $status_args, $codes_to_match );

        $post_ids = $wpdb->get_col(
            $wpdb->prepare(
                "SELECT DISTINCT p.ID
                FROM {$wpdb->posts} AS p
                INNER JOIN {$table} AS t
                    ON p.ID = t.element_id
                    AND t.element_type = %s
                WHERE p.post_type = %s
                    AND {$status_clause}
                    AND t.language_code IN ({$placeholders})",
                $values
            )
        );
    } else {
        $post_ids = array();
    }

    if ( empty( $post_ids ) ) {
        // Force an empty result set when nothing matches.
        $post_ids = array( 0 );
    } else {
        $post_ids = array_map( 'intval', $post_ids );
    }

    // Apply the filtered IDs to the query.
    $query->set( 'post__in', $post_ids );

    if ( ! $query->get( 'orderby' ) ) {
        // Default to ordering by date when not set.
        $query->set( 'orderby', 'date' );
    }
}
