import { Injectable, inject, signal } from '@angular/core';
import { BehaviorSubject, Observable, map, of, shareReplay, switchMap } from 'rxjs';
import { CategoryService } from '../../core/categories/category.service';
import { Category } from '../../core/categories/models/category-domain.model';

@Injectable({ providedIn: 'root' })
export class CategoryFacade {
  private readonly categoryService = inject(CategoryService);
  private readonly selectedCategoryId = new BehaviorSubject<number | null>(null);

  readonly allCategories = signal<Category[]>([]);
  readonly categoryTree = signal<Category[]>([]);
  readonly rootCategories = signal<Category[]>([]);
  readonly selectedCategory = signal<Category | null>(null);
  readonly breadcrumb = signal<Category[]>([]);
  readonly children = signal<Category[]>([]);
  readonly loading = signal(false);
  readonly error = signal<string | null>(null);

  readonly allCategories$ = this.categoryService.getAllCategories()
    .pipe(shareReplay({ bufferSize: 1, refCount: true }));
  readonly categoryTree$ = this.categoryService.getCategoryTree()
    .pipe(shareReplay({ bufferSize: 1, refCount: true }));
  readonly rootCategories$ = this.categoryService.getRootCategories()
    .pipe(shareReplay({ bufferSize: 1, refCount: true }));
  readonly selectedCategory$ = this.selectedCategoryId.pipe(
    switchMap(categoryId => categoryId == null ? of(null) : this.categoryService.getCategoryById(categoryId)),
    map(category => category ?? null),
    shareReplay({ bufferSize: 1, refCount: true })
  );
  readonly breadcrumb$ = this.selectedCategoryId.pipe(
    switchMap(categoryId => categoryId == null ? of([]) : this.categoryService.getBreadcrumb(categoryId)),
    shareReplay({ bufferSize: 1, refCount: true })
  );
  readonly children$ = this.selectedCategoryId.pipe(
    switchMap(categoryId => categoryId == null ? of([]) : this.categoryService.getChildren(categoryId)),
    shareReplay({ bufferSize: 1, refCount: true })
  );

  loadCategories(): void {
    this.loading.set(true);
    this.error.set(null);

    this.allCategories$.subscribe({
      next: (categories) => {
        this.allCategories.set(categories);
        this.loading.set(false);
      },
      error: () => {
        this.allCategories.set([]);
        this.error.set('Failed to load categories');
        this.loading.set(false);
      }
    });
  }

  selectCategory(categoryId: number | null): void {
    this.selectedCategoryId.next(categoryId);
  }

  syncSelectedCategoryState(): void {
    this.selectedCategory$.subscribe(category => this.selectedCategory.set(category));
    this.breadcrumb$.subscribe(breadcrumb => this.breadcrumb.set(breadcrumb));
    this.children$.subscribe(children => this.children.set(children));
  }

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

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

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

  getCategoryById(categoryId: number): Observable<Category | undefined> {
    return this.categoryService.getCategoryById(categoryId);
  }

  getBreadcrumb(categoryId: number): Observable<Category[]> {
    return this.categoryService.getBreadcrumb(categoryId);
  }

  getChildren(categoryId: number): Observable<Category[]> {
    return this.categoryService.getChildren(categoryId);
  }
}