<?php

namespace FleekDash\Controllers\Post;

use FleekDash\Core\TermsFetchException;

/**
 * Helper for post filter options (tags, labels) used in PostController.
 *
 * @package FleekDash\Controllers\Post
 */
class PostFilterOptionsHelper
{
    /**
     * Compute tag/term options for a post type.
     *
     * @param string $post_type
     * @return array<int, array<string, mixed>>
     * @throws TermsFetchException When terms fetch fails
     */
    public static function computeTagOptions(string $post_type): array
    {
        $taxonomy = self::resolveTagTaxonomy($post_type);
        $taxonomies = get_object_taxonomies($post_type, 'names');
        $terms = \get_terms([
            'taxonomy' => $taxonomy,
            'hide_empty' => false,
            'orderby' => 'count',
            'order' => 'DESC',
            'number' => 100
        ]);
        if (is_wp_error($terms)) {
            throw new TermsFetchException('Failed to fetch terms: ' . $terms->get_error_message());
        }
        if (empty($terms) && $taxonomy === 'post_tag' && in_array('category', $taxonomies)) {
            $terms = \get_terms([
                'taxonomy' => 'category',
                'hide_empty' => false,
                'orderby' => 'count',
                'order' => 'DESC',
                'number' => 100
            ]);
            $taxonomy = 'category';
        }
        $tag_options = [];
        foreach ($terms as $term) {
            $tag_options[] = [
                'id' => (string) $term->term_id,
                'name' => $term->name,
                'slug' => $term->slug,
                'count' => $term->count,
                'taxonomy' => $taxonomy
            ];
        }
        return $tag_options;
    }

    /**
     * Resolve which taxonomy to use for tags.
     *
     * @param string $post_type
     * @return string
     */
    public static function resolveTagTaxonomy(string $post_type): string
    {
        $taxonomies = get_object_taxonomies($post_type, 'names');
        $result = 'post_tag';
        if (in_array('post_tag', $taxonomies)) {
            $result = 'post_tag';
        } elseif (in_array('product_tag', $taxonomies)) {
            $result = 'product_tag';
        } elseif (!empty($taxonomies)) {
            foreach ($taxonomies as $tax) {
                if (strpos($tax, 'tag') !== false) {
                    $result = $tax;
                    break;
                }
            }
            if ($result === 'post_tag' && !in_array('post_tag', $taxonomies)) {
                $result = $taxonomies[0];
            }
        }
        return $result;
    }

    /**
     * Compute label (taxonomy + terms) options for a post type.
     *
     * @param string $post_type
     * @return array<int, array<string, mixed>>
     */
    public static function computeLabelOptions(string $post_type): array
    {
        $taxonomies = get_object_taxonomies($post_type, 'objects');
        $labels_data = [];

        foreach ($taxonomies as $taxonomy) {
            if (!self::shouldIncludeTaxonomyInLabels($post_type, $taxonomy)) {
                continue;
            }
            $terms = \get_terms([
                'taxonomy' => $taxonomy->name,
                'hide_empty' => false,
                'orderby' => 'name',
                'order' => 'ASC',
                'number' => 200
            ]);
            if (is_wp_error($terms)) {
                continue;
            }
            $term_options = [];
            foreach ($terms as $term) {
                $term_options[] = [
                    'id' => (string) $term->term_id,
                    'name' => $term->name,
                    'slug' => $term->slug,
                    'count' => $term->count
                ];
            }
            $labels_data[] = [
                'taxonomy' => $taxonomy->name,
                'taxonomyLabel' => $taxonomy->label,
                'terms' => $term_options
            ];
        }
        return $labels_data;
    }

    /**
     * Primary hierarchical taxonomy used by the category column (excluded from labels only).
     *
     * @param string $post_type
     * @return string
     */
    public static function getPrimaryCategoryTaxonomyName(string $post_type): string
    {
        $result = 'category';

        if ($post_type === 'post') {
            $result = 'category';
        } elseif ($post_type === 'product') {
            $result = 'product_cat';
        } else {
            $taxonomies = get_object_taxonomies($post_type, 'objects');
            foreach ($taxonomies as $taxonomy) {
                if ($taxonomy->hierarchical || $taxonomy->name === 'category') {
                    $result = $taxonomy->name;
                    break;
                }
            }
        }

        return $result;
    }

    /**
     * Whether a taxonomy belongs in the labels column / dropdown (not category column).
     *
     * @param string $post_type
     * @param \WP_Taxonomy $taxonomy
     * @return bool
     */
    public static function shouldIncludeTaxonomyInLabels(string $post_type, \WP_Taxonomy $taxonomy): bool
    {
        $skip_names = array('nav_menu', 'link_category', 'post_format');
        if (in_array($taxonomy->name, $skip_names, true)) {
            return false;
        }

        return $taxonomy->name !== self::getPrimaryCategoryTaxonomyName($post_type);
    }
}
