import { Component, NgZone, inject, OnInit } from '@angular/core';
import { ActivatedRoute, Data, ParamMap, Router, RouterModule } from '@angular/router';
import { combineLatest, filter, Observable, Subscription, tap, map, of } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { HttpResponse } from '@angular/common/http';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';

import SharedModule from 'app/shared/shared.module';
import { DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe } from 'app/shared/date';
import { FormsModule, ReactiveFormsModule, } from '@angular/forms';
import { SORT, ITEM_DELETED_EVENT, DEFAULT_SORT_DATA } from 'app/config/navigation.constants';
import { IEmissionFactor } from '../../emission-factor.model';
import { IVariableScope } from 'app/entities/variable-scope/variable-scope.model';
import { IVariableCategory } from 'app/entities/variable-category/variable-category.model';
import { VariableScopeService } from 'app/entities/variable-scope/service/variable-scope.service';
import { VariableCategoryService } from 'app/entities/variable-category/service/variable-category.service';
import { EntityArrayResponseType, EmissionFactorService } from '../../service/emission-factor.service';
import { EmissionFactorSearchFormService, EmissionFactorSearchFormGroup } from '../emission-factor-search-form.service';
import { FormatHelper } from 'app/shared/utils/format-helper';
import { IPeriod } from 'app/entities/period/period.model';
import { PeriodService } from 'app/entities/period/service/period.service';

@Component({
  standalone: true,
  selector: 'jhi-emission-factor-public',
  templateUrl: './emission-factor-public.component.html',
  styleUrl: './emission-factor-public.component.css',
  imports: [
    RouterModule,
    FormsModule,
    ReactiveFormsModule,
    SharedModule,
    DurationPipe,
    FormatMediumDatetimePipe,
    FormatMediumDatePipe,
    MatProgressSpinnerModule
  ],
})
export class EmissionFactorPublicComponent implements OnInit {
  subscriptionWorkOrganization!: Subscription;  // Store the subscription
  subscription: Subscription | null = null;
  emissionFactors?: IEmissionFactor[];
  isLoading = false;
  isExporting: boolean = false;

  variableScopesSharedCollection: IVariableScope[] = [];
  categoriesSharedCollection: IVariableCategory[] = [];
  periodYears: number[] = [];

  public router = inject(Router);
  protected variableScopeService = inject(VariableScopeService);
  protected variableCategoryService = inject(VariableCategoryService);
  protected periodService = inject(PeriodService);
  protected emissionFactorService = inject(EmissionFactorService);
  protected emissionFactorSearchFormService = inject(EmissionFactorSearchFormService);
  protected activatedRoute = inject(ActivatedRoute);
  protected modalService = inject(NgbModal);
  protected ngZone = inject(NgZone);

  searchForm: EmissionFactorSearchFormGroup = this.emissionFactorSearchFormService.createEmissionFactorSearchFormGroup();
  trackId = (_index: number, item: IEmissionFactor): number => this.emissionFactorService.getEntityIdentifier(item);

  comparePeriod = (o1: IPeriod | null, o2: IPeriod | null): boolean =>
    this.periodService.compareEntity(o1, o2);

  compareCategory = (o1: IVariableCategory | null, o2: IVariableCategory | null): boolean =>
    this.variableCategoryService.compareEntity(o1, o2);
    
  compareVariableScope = (o1: IVariableScope | null, o2: IVariableScope | null): boolean =>
    this.variableScopeService.compareEntity(o1, o2);

  ngOnInit(): void {
    // Listen to changes to the scope filter property
    this.searchForm.get('variableScopeId')?.valueChanges.subscribe((scopeId) => {
      this.loadCategoriesOfSelectedScope(scopeId);
      this.searchForm.get('variableCategoryId')?.setValue(null);
    });

    this.loadRelationshipsOptions();
  }

  onSearch(): void {
	  this.load();
  }
  
  load(): void {
    this.queryBackend().subscribe({
      next: (res: EntityArrayResponseType) => {
        this.onResponseSuccess(res);
      },
    });
  }

  protected onResponseSuccess(response: EntityArrayResponseType): void {
    const dataFromBody = this.fillComponentAttributesFromResponseBody(response.body);

    this.emissionFactors = dataFromBody;
  }

  protected fillComponentAttributesFromResponseBody(data: IEmissionFactor[] | null): IEmissionFactor[] {
    return data ?? [];
  }

  protected queryBackend(): Observable<EntityArrayResponseType> {
    const searchModel = this.emissionFactorSearchFormService.getEmissionFactor(this.searchForm);

    // Without YEAR, can't search
    if (!searchModel.year) return of(new HttpResponse<IEmissionFactor[]>({ body: [] }));

    let searchScopeId = "ALL";
    if (searchModel.variableScopeId) searchScopeId = searchModel.variableScopeId.toString();
    
    let searchCategoryId = "ALL";
    if (searchModel.variableCategoryId) searchCategoryId = searchModel.variableCategoryId.toString();

    return this.emissionFactorService.queryBySearch(searchModel.year, searchScopeId, searchCategoryId).pipe(tap(() => (this.isLoading = false)));
  }
  
  protected loadCategoriesOfSelectedScope(scopeId: number|null|undefined): void {
    if (scopeId) {
      this.variableCategoryService
          .queryByScopeForFactor(scopeId)
          .pipe(map((res: HttpResponse<IVariableCategory[]>) => res.body ?? []))
          .subscribe((cats: IVariableCategory[]) => (this.categoriesSharedCollection = cats));
    } else {
      this.categoriesSharedCollection = [];
    }
  }
  
  protected loadRelationshipsOptions(): void {
      this.variableScopeService
          .queryForFactor()
          .pipe(map((res: HttpResponse<IVariableScope[]>) => res.body ?? []))
          .subscribe((scopes: IVariableScope[]) => (this.variableScopesSharedCollection = scopes));

      this.periodService
          .query()
          .pipe(map((res: HttpResponse<IPeriod[]>) => res.body ?? []))
          .subscribe((periods: IPeriod[]) => { 
            this.periodYears = Array.from(
              new Set(
                periods
                  .map(period => period.endDate?.year()) // extract year
                  .filter((year): year is number => year !== undefined && year !== null) // remove undefined/null
              )
            ).sort((a, b) => b - a); // optional: sort years descending

            // Set first Year as default. It's mandatory to select a Year
            this.searchForm.get('year')?.setValue(this.periodYears[0]);
          });
  }
  
  formatValue(value: number): string {
    return FormatHelper.formatDecimalValue(value);
  }

  export(): void {
    this.isExporting = true;
    const queryObject: any = {
      eagerload: true,
    };
	
    const searchModel = this.emissionFactorSearchFormService.getEmissionFactor(this.searchForm);
    if (searchModel) {
      // Apply conditions
      this.emissionFactorSearchFormService.applySearchConditionsToQueryObject(queryObject, searchModel);    
    }

    this.emissionFactorService.export(queryObject).subscribe((blob: Blob) => {
      const a = document.createElement('a');
      const objectUrl = URL.createObjectURL(blob);
      a.href = objectUrl;
      a.download = 'report.xlsx';
      a.click();
      URL.revokeObjectURL(objectUrl);

      this.isExporting = false;
    });
  }
}
