<?php

namespace FuseCommerce\Services;

use FuseCommerce\Repositories\ProductRepository;

/**
 * Service for building hierarchical category tree structure
 */
class CategoryIndexerService {
    private ProductRepository $product_repository;

    public function __construct( ProductRepository $product_repository ) {
        $this->product_repository = $product_repository;
    }

    /**
     * Build hierarchical category tree
     * Only includes categories used by published products
     *
     * @return array Hierarchical array of categories
     */
    public function buildCategoryTree(): array {
        // Get only categories used by published products
        $used_category_ids = $this->product_repository->getUsedCategoryIds();

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

        // Get all category terms (including parents not directly used)
        // We need parent categories to build the tree structure
        $all_categories = $this->getCategoriesWithParents( $used_category_ids );

        // Convert terms to array format
        $categories_array = $this->convertTermsToArray( $all_categories );

        // Build hierarchical tree structure
        $tree = $this->buildTree( $categories_array );

        return $tree;
    }

    /**
     * Get categories and their parent categories
     * This ensures we can build a complete tree structure
     *
     * @param array $category_ids Array of category term IDs
     * @return array Array of WP_Term objects
     */
    private function getCategoriesWithParents( array $category_ids ): array {
        $all_category_ids = $category_ids;

        // Get parent category IDs for each category
        foreach ( $category_ids as $cat_id ) {
            $ancestors = get_ancestors( $cat_id, 'product_cat', 'taxonomy' );

            if ( ! empty( $ancestors ) ) {
                $all_category_ids = array_merge( $all_category_ids, $ancestors );
            }
        }

        // Remove duplicates
        $all_category_ids = array_unique( $all_category_ids );

        // Get all terms
        $terms = get_terms( [
            'taxonomy'   => 'product_cat',
            'include'    => $all_category_ids,
            'hide_empty' => false,
            'orderby'    => 'name',
            'order'      => 'ASC',
        ] );

        if ( is_wp_error( $terms ) ) {
            return [];
        }

        return $terms;
    }

    /**
     * Convert WP_Term objects to array format
     *
     * @param array $terms Array of WP_Term objects
     * @return array Array of category data
     */
    private function convertTermsToArray( array $terms ): array {
        $categories = [];

        foreach ( $terms as $term ) {
            $categories[] = [
                'id'       => $term->term_id,
                'name'     => $term->name,
                'slug'     => $term->slug,
                'parent'   => $term->parent,
                'count'    => $term->count,
                'children' => [],
            ];
        }

        return $categories;
    }

    /**
     * Build hierarchical tree structure from flat array
     *
     * @param array $categories Flat array of categories
     * @param int $parent_id Parent category ID (0 for root level)
     * @return array Hierarchical tree
     */
    private function buildTree( array $categories, int $parent_id = 0 ): array {
        $tree = [];

        foreach ( $categories as $category ) {
            if ( $category['parent'] === $parent_id ) {
                // Find children recursively
                $children = $this->buildTree( $categories, $category['id'] );

                if ( ! empty( $children ) ) {
                    $category['children'] = $children;
                }

                $tree[] = $category;
            }
        }

        return $tree;
    }

    /**
     * Build a flat list of categories (alternative to tree structure)
     * Useful if hierarchical structure is not needed
     *
     * @return array Flat array of categories
     */
    public function buildFlatCategoryList(): array {
        $used_category_ids = $this->product_repository->getUsedCategoryIds();

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

        $terms = get_terms( [
            'taxonomy'   => 'product_cat',
            'include'    => $used_category_ids,
            'hide_empty' => false,
            'orderby'    => 'name',
            'order'      => 'ASC',
        ] );

        if ( is_wp_error( $terms ) ) {
            return [];
        }

        $categories = [];

        foreach ( $terms as $term ) {
            $categories[] = [
                'id'     => $term->term_id,
                'name'   => $term->name,
                'slug'   => $term->slug,
                'parent' => $term->parent,
                'count'  => $term->count,
            ];
        }

        return $categories;
    }
}
