<?php

declare(strict_types=1);

namespace App\Business\Product;

use App\Models\DberpProductCategory;
use Illuminate\Support\Collection;

final class ProductCategoryTreeService
{
    /**
     * @return array<int, string>
     */
    public function options(?int $exceptId = null): array
    {
        $categories = DberpProductCategory::query()
            ->select(['id', 'name', 'parent_id', 'sort_order'])
            ->when($exceptId !== null, fn ($query) => $query->whereKeyNot($exceptId))
            ->orderBy('sort_order')
            ->orderBy('id')
            ->get();

        return $this->flattenOptions($categories);
    }

    /**
     * @param  Collection<int, DberpProductCategory>  $categories
     * @return array<int, string>
     */
    private function flattenOptions(Collection $categories): array
    {
        $grouped = $categories->groupBy(fn (DberpProductCategory $category): int => (int) ($category->parent_id ?? 0));
        $options = [];

        $appendChildren = function (int $parentId, int $depth) use (&$appendChildren, &$grouped, &$options): void {
            /** @var Collection<int, DberpProductCategory> $children */
            $children = $grouped->get($parentId, collect());

            foreach ($children as $category) {
                $prefix = str_repeat('　', max(0, $depth));
                $options[(int) $category->getKey()] = $prefix.$category->name;
                $appendChildren((int) $category->getKey(), $depth + 1);
            }
        };

        $appendChildren(0, 0);

        return $options;
    }
}