<?php

// If this file is called directly, abort.
if (!defined('WPINC')) {
	die;
}

class ProductCategoriesController {
	private $termCache = [];

	public function getCategories() {
		$terms = get_terms([
			'taxonomy' => 'product_cat',
			'hide_empty' => false,
		]);

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

		foreach ($terms as $term) {
			$this->termCache[$term->term_id] = $term;
		}

		$categories = [];
		foreach ($terms as $term) {
			$categories[] = [
				'id' => (int) $term->term_id,
				'name' => $term->name ?? "",
				'url' => $this->getCategoryUrl($term),
				'parent_id' => $term->parent ? (int) $term->parent : "1",
				'parent_name' => $this->getParentName($term),
				'level' => (string) $this->getCategoryLevel($term),
				'path' => $this->getCategoryPath($term),
				'image' => $this->getCategoryImage($term),
				'category_size' => $this->getCategoryProductCount($term),
			];
		}

		return $categories;
	}

	private function getCategoryProductCount($term) {
		if (isset($term->count)) {
			return (int) $term->count;
		}
		$fresh = get_term($term->term_id, 'product_cat');
		return $fresh && !is_wp_error($fresh) ? (int) $fresh->count : 0;
	}

	private function getParentName($term) {
		if ($term->parent && isset($this->termCache[$term->parent])) {
			return $this->termCache[$term->parent]->name;
		}
		return "";
	}

	private function getCategoryLevel($term) {
		$level = 2;
		$current = $term;

		while ($current->parent && isset($this->termCache[$current->parent])) {
			$current = $this->termCache[$current->parent];
			$level++;
		}
		return $level;
	}

	private function getCategoryImage($term) {
		$thumbnail_id = get_term_meta($term->term_id, 'thumbnail_id', true);
		return $thumbnail_id ? wp_get_attachment_url($thumbnail_id) : "";
	}

	private function getCategoryUrl($term) {
		$url = get_term_link($term);
		return !is_wp_error($url) ? $url : null;
	}

	private function getCategoryPath($term) {
		$segments = [];
		$current = $term;

		while ($current->parent && isset($this->termCache[$current->parent])) {
			$parent = $this->termCache[$current->parent];
			array_unshift($segments, $parent->name);
			$current = $parent;
		}

		$segments[] = $term->name;
		return implode(' > ', $segments);
	}
}