<?php
declare(strict_types=1);

namespace WP_AUX\Services;

use WHOOP\Entities\Elements\A;
use WP_AUX\Entities\AuxCF\PageFields\Taxonomy\TaxonomyLogoFieldEntity;

/**
 * Utilities for working with taxonomy terms
 * @since 1.0.0
 */
class TaxonomyTermsService
{
  /**
   * Get the most-used terms, optionally within a specific post type
   * @return \WP_Term[]
   * @since 1.0.0
   */
  public static function getMostUsedTerms(string $taxonomy, ?string $postType = null, int $limit = 5): array
  {
    global $wpdb;

    $arguments = [
      $taxonomy,
    ];

    $whereString = "WHERE tax.taxonomy = '%s'";
    if (!empty($postType)) {
      $arguments[] = $postType;
      $whereString .= " AND post.post_type = '%s'";
    }
    $whereString .= " AND post.post_status = 'publish'";

    // Exclude Uncategorized category if querying categories
    if ( 'category' === $taxonomy ) {
      $arguments[] = 'uncategorized';
      $whereString .= " AND term.slug != '%s'";
    }

    $arguments[] = $limit;

    $query = $wpdb->prepare(
      "SELECT term.*, tr.term_taxonomy_id, COUNT(*) AS use_count from $wpdb->terms AS term
                INNER JOIN $wpdb->term_taxonomy AS tax ON term.term_id = tax.term_id
                INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tax.term_taxonomy_id
                INNER JOIN $wpdb->posts AS post ON post.ID = tr.object_id
                $whereString
                GROUP BY term.term_id ORDER BY use_count DESC LIMIT %d",
      $arguments
    );

    $results = $wpdb->get_results( $query );

    if (empty($results)) {
      return [];
    }

    $terms = get_terms([
      'term_taxonomy_id' => array_column($results, 'term_taxonomy_id'),
      'orderby' => 'count',
      'order' => 'DESC',
    ]);

    // Additional filter to ensure Uncategorized is excluded (in case get_terms filter doesn't apply)
    if ( 'category' === $taxonomy && is_array( $terms ) ) {
      $terms = array_filter( $terms, function( $term ) {
        if ( is_object( $term ) && isset( $term->slug ) ) {
          return $term->slug !== 'uncategorized';
        }
        return true;
      } );
      $terms = array_values( $terms );
    }

    return $terms;
  }

  /**
   * Get the link to a term
   * @since 1.0.0
   */
  public static function termLink(\WP_Term $term, bool $includeImage = true): ?A
  {
    $termContent = '';

    if ($includeImage && $termImage = self::getTermField(TaxonomyLogoFieldEntity::$name, $term->term_id)) {
      $termContent .= sprintf(
        '<img src="%s" width="%s" class="term-icon" alt="">',
        $termImage['sizes']['thumbnail'],
        $termImage['sizes']['thumbnail-width']
      );
    }

    $termContent .= $term->name;

    return HtmlService::link($termContent, get_term_link($term));
  }

  /**
   * Get an ACF field value for a term
   * @since 1.0.0
   */
  public static function getTermField(string $fieldName, int|string|\WP_Term $term): mixed
  {
    if ($term instanceof \WP_Term) {
      $termId = $term->term_id;
    } else {
      $termId = $term;
    }

    return get_field($fieldName, 'term_'.$termId);
  }

  /**
   * Register taxonomy terms-related actions and filters
   * @since 1.0.2
   */
  public static function prepareHooks(): void
  {
    // Exclude Uncategorized category from front-end display
    add_filter( 'get_terms', function( $terms, $taxonomies, $args ) {
      // Only filter on front-end, not in admin
      if ( is_admin() ) {
        return $terms;
      }

      // Check if categories are being queried
      if ( ! is_array( $taxonomies ) ) {
        $taxonomies = [ $taxonomies ];
      }

      if ( ! in_array( 'category', $taxonomies, true ) ) {
        return $terms;
      }

      // Filter out Uncategorized category
      if ( is_array( $terms ) ) {
        $terms = array_filter( $terms, function( $term ) {
          if ( is_object( $term ) ) {
            // Exclude by slug
            if ( isset( $term->slug ) && $term->slug === 'uncategorized' ) {
              return false;
            }
          }
          return true;
        } );

        // Re-index array after filtering
        $terms = array_values( $terms );
      }

      return $terms;
    }, 10, 3 );

    // Also filter get_categories() results
    add_filter( 'get_categories', function( $categories ) {
      // Only filter on front-end, not in admin
      if ( is_admin() ) {
        return $categories;
      }

      // Filter out Uncategorized category
      $categories = array_filter( $categories, function( $category ) {
        if ( is_object( $category ) ) {
          // Exclude Uncategorized category by slug
          if ( isset( $category->slug ) && $category->slug === 'uncategorized' ) {
            return false;
          }
        }
        return true;
      } );

      // Re-index array after filtering
      return array_values( $categories );
    }, 10, 1 );
  }
}
