<?php

namespace FleekDash\API\Posts;

/**
 * Posts Query Builder
 *
 * Handles building WP_Query arguments for posts retrieval
 * Extracted from FLEEKDASH_Posts_Optimized_API for better organization
 *
 * @package FleekDash\API\Posts
 * @since 2.2.0
 */
class PostsQueryBuilder
{
    /**
     * Build complete query arguments
     *
     * @param array $params Request parameters
     * @return array WP_Query arguments
     */
    public function buildQueryArgs($params)
    {
        $args = [
            'posts_per_page' => $params['per_page'] ?? 500,
            'paged' => $params['page'] ?? 1,
            'orderby' => $params['orderby'] ?? 'date',
            'order' => $params['order'] ?? 'DESC',
            'meta_query' => [],
            'tax_query' => [],
            'no_found_rows' => true,
            'update_post_meta_cache' => false,
            'update_post_term_cache' => false,
            'ignore_sticky_posts' => true,
            'cache_results' => false,
        ];

        // Apply filters
        $args = $this->handlePostTypeFilter($args, $params);
        $args = $this->handleStatusFilter($args, $params);

        return $args;
    }

    /**
     * Handle post type filtering
     *
     * @param array $args Current query args
     * @param array $params Request parameters
     * @return array Modified query args
     */
    public function handlePostTypeFilter($args, $params)
    {
        $post_type = $params['post_type'] ?? 'all';

        if ($post_type !== 'all') {
            // Validate post type
            if (!\post_type_exists($post_type)) {
                return $args; // Return unchanged if invalid
            }
            $args['post_type'] = $post_type;
        } else {
            // Get all public post types
            $post_types = \get_post_types(['public' => true], 'names');

            // Exclude internal types
            $exclude_types = [
                'attachment',
                'revision',
                'nav_menu_item',
                'custom_css',
                'customize_changeset',
                'oembed_cache',
                'user_request',
                'wp_block',
            ];

            $args['post_type'] = array_values(array_diff($post_types, $exclude_types));
        }

        return $args;
    }

    /**
     * Handle post status filtering
     *
     * @param array $args Current query args
     * @param array $params Request parameters
     * @return array Modified query args
     */
    public function handleStatusFilter($args, $params)
    {
        $status = $params['status'] ?? 'all';
        $post_type = $params['post_type'] ?? 'post';

        if ($status !== 'all') {
            // Handle comma-separated statuses
            if (strpos($status, ',') !== false) {
                $args['post_status'] = array_map('trim', explode(',', $status));
            } else {
                $args['post_status'] = $status;
            }
        } else {
            $args['post_status'] = $this->getAllAvailableStatuses($post_type);
        }

        return $args;
    }

    /**
     * Get all available post statuses (excluding trash, draft, etc)
     *
     * @param string $post_type Post type to check
     * @return array Available statuses
     */
    private function getAllAvailableStatuses($post_type)
    {
        // Get registered statuses
        $all_statuses = get_post_statuses();
        $excluded_statuses = ['trash', 'draft', 'auto-draft', 'inherit'];

        // Filter out excluded statuses
        $included_statuses = [];
        foreach ($all_statuses as $status_key => $status_label) {
            if (!in_array($status_key, $excluded_statuses)) {
                $included_statuses[] = $status_key;
            }
        }

        // Get custom statuses from database
        global $wpdb;
        $custom_statuses = $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT post_status FROM {$wpdb->posts}
             WHERE post_type = %s
             AND post_status NOT IN ('" . implode("','", $excluded_statuses) . "')",
            $post_type
        ));

        // Merge and remove duplicates
        return array_unique(array_merge($included_statuses, $custom_statuses));
    }

    /**
     * Add search filter to query args
     *
     * @param array $args Current query args
     * @param string $search Search term
     * @return array Modified query args
     */
    public function addSearchFilter($args, $search)
    {
        if (!empty($search)) {
            $args['s'] = \sanitize_text_field($search);
        }

        return $args;
    }

    /**
     * Add taxonomy filters to query args
     *
     * @param array $args Current query args
     * @param array $taxonomy_filters Taxonomy filters
     * @return array Modified query args
     */
    public function addTaxonomyFilters($args, $taxonomy_filters)
    {
        if (empty($taxonomy_filters) || !is_array($taxonomy_filters)) {
            return $args;
        }

        $tax_query = [];

        foreach ($taxonomy_filters as $taxonomy => $terms) {
            if (empty($terms) || !taxonomy_exists($taxonomy)) {
                continue;
            }

            // Convert comma-separated string to array
            if (is_string($terms)) {
                $terms = array_map('trim', explode(',', $terms));
            }

            $tax_query[] = [
                'taxonomy' => $taxonomy,
                'field' => 'term_id',
                'terms' => array_map('intval', $terms),
            ];
        }

        if (!empty($tax_query)) {
            $args['tax_query'] = $tax_query;

            // Add relation if multiple taxonomies
            if (count($tax_query) > 1) {
                $args['tax_query']['relation'] = 'AND';
            }
        }

        return $args;
    }

    /**
     * Add meta query filters
     *
     * @param array $args Current query args
     * @param array $meta_filters Meta filters
     * @return array Modified query args
     */
    public function addMetaFilters($args, $meta_filters)
    {
        if (empty($meta_filters) || !is_array($meta_filters)) {
            return $args;
        }

        $meta_query = [];

        foreach ($meta_filters as $meta_key => $meta_value) {
            if (empty($meta_key)) {
                continue;
            }

            $meta_query[] = [
                'key' => \sanitize_text_field($meta_key),
                'value' => \sanitize_text_field($meta_value),
                'compare' => '=',
            ];
        }

        if (!empty($meta_query)) {
            $args['meta_query'] = $meta_query;

            // Add relation if multiple meta queries
            if (count($meta_query) > 1) {
                $args['meta_query']['relation'] = 'AND';
            }
        }

        return $args;
    }
}
