<?php

namespace FleekDash\Controllers\Posts;

/**
 * Helper for Posts Actions - Stats and status aggregation.
 * Extracted to reduce cognitive complexity in Actions::getPostsStats().
 *
 * @package FleekDash\Controllers\Posts
 */
class PostsStatsHelper
{
    private const EXCLUDED_FROM_FILTERS = ['auto-draft', 'inherit'];

    /**
     * Get total post count (excluding auto-draft, inherit, trash, draft).
     *
     * @param string $post_type Post type
     * @return int
     */
    public static function getTotalCount(string $post_type): int
    {
        global $wpdb;
        $excluded = \array_merge(self::EXCLUDED_FROM_FILTERS, ['trash', 'draft']);
        $placeholders = \implode(',', \array_fill(0, \count($excluded), '%s'));

        $result = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->posts}
             WHERE post_type = %s
             AND post_status NOT IN ({$placeholders})",
            \array_merge([$post_type], $excluded)
        ));

        return (int) $result;
    }

    /**
     * Get post counts grouped by status.
     *
     * @param string $post_type Post type
     * @return array<string, int>
     */
    public static function getStatusCounts(string $post_type): array
    {
        global $wpdb;
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT post_status, COUNT(*) as count
             FROM {$wpdb->posts}
             WHERE post_type = %s
             GROUP BY post_status",
            $post_type
        ), ARRAY_A);

        $status_counts = [];
        foreach ($rows as $row) {
            $status_counts[$row['post_status']] = (int) $row['count'];
        }

        return $status_counts;
    }

    /**
     * Collect all available statuses from WP, globals, and database.
     *
     * @param string $post_type Post type
     * @return array<string, string> status_key => label
     */
    public static function collectAllStatuses(string $post_type): array
    {
        global $wpdb;
        $all_statuses = [];

        $wp_statuses = \get_post_statuses();
        foreach ($wp_statuses as $status_key => $status_label) {
            $all_statuses[$status_key] = $status_label;
        }

        $all_status_objects = $GLOBALS['wp_post_statuses'] ?? [];
        foreach ($all_status_objects as $status_key => $status_obj) {
            if (isset($status_obj->label) && !\in_array($status_key, self::EXCLUDED_FROM_FILTERS, true)) {
                $all_statuses[$status_key] = $status_obj->label;
            }
        }

        $db_statuses = $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT post_status FROM {$wpdb->posts} WHERE post_type = %s",
            $post_type
        ));

        foreach ($db_statuses as $status_key) {
            $all_statuses = self::addStatusIfMissing($all_statuses, $status_key);
        }

        $all_db_statuses = $wpdb->get_col("SELECT DISTINCT post_status FROM {$wpdb->posts}");
        foreach ($all_db_statuses as $status_key) {
            $all_statuses = self::addStatusIfMissing($all_statuses, $status_key);
        }

        return $all_statuses;
    }

    /**
     * Add status with label if not already present.
     *
     * @param array<string, string> $all_statuses
     * @param string $status_key
     * @return array<string, string>
     */
    private static function addStatusIfMissing(array $all_statuses, string $status_key): array
    {
        if (isset($all_statuses[$status_key]) || \in_array($status_key, self::EXCLUDED_FROM_FILTERS, true)) {
            return $all_statuses;
        }

        $status_obj = \get_post_status_object($status_key);
        $label = $status_obj && isset($status_obj->label)
            ? $status_obj->label
            : \ucfirst(\str_replace(['_', '-'], ' ', $status_key));

        $all_statuses[$status_key] = $label;

        return $all_statuses;
    }

    /**
     * Build stats, labels, and options from collected statuses.
     *
     * @param int $total_count
     * @param array<string, int> $status_counts
     * @param array<string, string> $all_statuses
     * @return array{stats: array, labels: array, options: array}
     */
    public static function buildStatsPayload(int $total_count, array $status_counts, array $all_statuses): array
    {
        $stats = ['total' => $total_count];
        $status_labels = [];
        $all_status_options = [];

        foreach ($all_statuses as $status_key => $status_label) {
            $count = $status_counts[$status_key] ?? 0;

            if ($count > 0) {
                $stats[$status_key] = $count;
            }

            $status_labels[$status_key] = $status_label;
            $all_status_options[] = [
                'value' => $status_key,
                'label' => $status_label,
                'count' => $count,
            ];
        }

        return [
            'stats' => $stats,
            'labels' => $status_labels,
            'all_status_options' => $all_status_options,
        ];
    }

    /**
     * Whether the current user can open post-new.php for this post type (matches wp-admin/post-new.php checks).
     *
     * @param string $post_type Post type slug
     */
    public static function canCreateNewInAdmin(string $post_type): bool
    {
        $can = false;
        if (\post_type_exists($post_type)) {
            $pto = \get_post_type_object($post_type);
            $cap = ($pto && $pto->show_ui !== false && isset($pto->cap->create_posts))
                ? (string) $pto->cap->create_posts
                : '';
            if ($cap !== '') {
                $can = \current_user_can($cap);
            }
        }

        return $can;
    }

    /**
     * Plural admin label for a post type (same as WP_Post_Type::$label).
     *
     * @param string $post_type Post type slug
     */
    public static function getPostTypeDisplayLabel(string $post_type): string
    {
        $label = '';
        if (\post_type_exists($post_type)) {
            $pto = \get_post_type_object($post_type);
            if ($pto && isset($pto->label) && \is_string($pto->label) && $pto->label !== '') {
                $label = $pto->label;
            }
        }

        return $label !== '' ? $label : $post_type;
    }
}
