import { Injectable, inject } from '@angular/core';
import { Observable, map, shareReplay } from 'rxjs';
import { CATEGORY_REPOSITORY } from './category-repository.token';
import { CategoryMapper } from './mappers/category.mapper';
import { Category } from './models/category-domain.model';
import { CategoryTreeUtils } from './utils/category-tree.utils';

@Injectable({ providedIn: 'root' })
export class CategoryService {
  private readonly repository = inject(CATEGORY_REPOSITORY);

  private readonly categories$ = this.repository.getCategories().pipe(
    map(dtos => CategoryMapper.toDomainList(dtos)),
    shareReplay({ bufferSize: 1, refCount: true })
  );

  getAllCategories(): Observable<Category[]> {
    return this.categories$;
  }

  getCategoryTree(): Observable<Category[]> {
    return this.categories$.pipe(map(categories => CategoryTreeUtils.toTree(categories)));
  }

  getRootCategories(): Observable<Category[]> {
    return this.getCategoryTree();
  }

  getCategoryById(categoryId: number): Observable<Category | undefined> {
    return this.getCategoryTree().pipe(map(tree => CategoryTreeUtils.findById(tree, categoryId)));
  }

  getChildren(categoryId: number): Observable<Category[]> {
    return this.categories$.pipe(map(categories => CategoryTreeUtils.getChildren(categories, categoryId)));
  }

  getBreadcrumb(categoryId: number): Observable<Category[]> {
    return this.categories$.pipe(map(categories => CategoryTreeUtils.getBreadcrumb(categories, categoryId)));
  }

  getParent(categoryId: number): Observable<Category | undefined> {
    return this.categories$.pipe(map(categories => CategoryTreeUtils.getParent(categories, categoryId)));
  }

  isLeaf(category: Category): boolean {
    return CategoryTreeUtils.isLeaf(category);
  }
}