/*
 * Copyright (C) 2025 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
import {SCLanguage, SCThingTranslator, SCThingType, SCTranslations} from '@openstapps/core';
import {ContextMenuService} from './context-menu.service';
import {FilterContext, FilterFacet, SortContext, SortContextOption} from './context-type.js';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
import {ModalController} from '@ionic/angular/standalone';
import {Component, Input, OnInit, OnDestroy} from '@angular/core';
import {Subject, takeUntil} from 'rxjs';

@Component({
  selector: 'stapps-context-menu-modal',
  templateUrl: './context-menu-modal.html',
})
export class ContextMenuModalComponent implements OnInit, OnDestroy {
  @Input() contextMenuService: ContextMenuService;

  compactFilterOptionCount = 5;

  filterOption: FilterContext;

  sortOption: SortContext;

  language: keyof SCTranslations<SCLanguage>;

  translator: SCThingTranslator;

  scThingType = SCThingType;

  // Using a subject to manage subscriptions for clean-up
  private readonly destroy$ = new Subject<void>();

  constructor(
    private translateService: TranslateService,
    private readonly modalController: ModalController,
  ) {
    this.language = this.translateService.currentLang as keyof SCTranslations<SCLanguage>;
    this.translator = new SCThingTranslator(this.language);

    this.translateService.onLangChange.pipe(takeUntilDestroyed()).subscribe((event: LangChangeEvent) => {
      this.language = event.lang as keyof SCTranslations<SCLanguage>;
      this.translator = new SCThingTranslator(this.language);
    });
  }

  ngOnInit(): void {
    const initialFilter = this.contextMenuService.filterOptions.getValue();
    if (initialFilter) {
      this.filterOption = initialFilter;
    }

    const initialSort = this.contextMenuService.sortOptions.getValue();
    if (initialSort) {
      this.sortOption = initialSort;
    }

    // Move the subscription logic here. It's now safe to access this.contextMenuService.
    this.contextMenuService.filterContextChanged$.pipe(takeUntil(this.destroy$)).subscribe(fc => {
      if (fc) {
        this.filterOption = fc;
      }
    });

    this.contextMenuService.sortContextChanged$.pipe(takeUntil(this.destroy$)).subscribe(sc => {
      if (sc) {
        this.sortOption = sc;
      }
    });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  get facets(): FilterFacet[] {
    return this.filterOption?.options?.filter(it => it.buckets.length > 0) || [];
  }

  resetFilter(option: FilterContext) {
    for (const facet of option.options) {
      for (const bucket of facet.buckets) {
        bucket.checked = false;
      }
    }
    this.contextMenuService.contextFilterChanged(this.filterOption);
  }

  filterChanged = () => {
    this.contextMenuService.contextFilterChanged(this.filterOption);
  };

  sortChanged(option: SortContext, value: SortContextOption) {
    if (option.value === value.value) {
      if (value.reversible) {
        option.reversed = !option.reversed;
      }
    } else {
      option.value = value.value;
      if (value.reversible) {
        option.reversed = false;
      }
    }
    this.contextMenuService.contextSortChanged(option);
  }

  getTranslatedPropertyValue(onlyForType: SCThingType, field: string, key?: string): string | undefined {
    return this.translator.translatedPropertyValue(onlyForType, field, key);
  }

  dismiss() {
    this.modalController.dismiss();
  }
}
