import { BehaviorSubject, catchError, map, retry, shareReplay, Subject, switchMap, tap } from 'rxjs';
import * as util from '../_shared/utils/util';
import { ChangeDetectionStrategy, Component, ElementRef, HostListener, inject, input, output, ViewChild, ViewEncapsulation } from '@angular/core';
import { GridItem, InvoiceDistributeService, InvoiceSelection } from './invoice-distribute.service';
import { Title } from '@angular/platform-browser';
import { CustomFormBuilder } from '../_shared/services/custom-form-builder.service';
import { MessageService } from '../_shared/services/message.service';
import { State } from '@progress/kendo-data-query';
import { FAST_KENDO_COMMON, FAST_PAGE_COMMON } from '../app.config';
import { ActivatedRoute } from '@angular/router';
import { InvoiceGasService } from '../invoice-gas/invoice-gas.service';
import { FastGridComponent } from '../_shared/elements/fast-grid.component';
import { ToastService } from '../_shared/services/fast-toast.service';

@Component({
  selector: 'app-invoice-distribute',
  imports: [FAST_PAGE_COMMON, FAST_KENDO_COMMON],
  templateUrl: './invoice-distribute.component.html',
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class InvoiceDistributeComponent {
  @ViewChild("grid", { read: ElementRef }) fastGridEl: ElementRef;
  @ViewChild('grid') grid: FastGridComponent;
  @HostListener('window:resize') onResize() {
    //this function is empty but for some reason it helps the window to resize faster
  };

  util = util;

  mySelection = input.required<number[]>();
  gridData: GridItem[] = [];
  closed = output();
  gridScrollPosition: util.GridScrollPosition = { topPos: 0, leftPos: 0 };
  invoicesSelection: InvoiceSelection[] = [];

  loading$ = new BehaviorSubject<boolean>(true);
  distribute$ = new Subject<number>();
  refreshItems$ = new BehaviorSubject<string>(null)

  //injects
  service = inject(InvoiceDistributeService);
  fb = inject(CustomFormBuilder);
  messageService = inject(MessageService);
  titleService = inject(Title);
  toast = inject(ToastService);
  activatedRoute = inject(ActivatedRoute);
  InvoiceGasOverviewService = inject(InvoiceGasService);

  state: State = {
    filter: null,
    group: null,
    skip: 0,
    sort: [
      { field: 'Month', dir: 'asc' },
    ],
    take: 50
  };

  items$ = this.refreshItems$.pipe(
    switchMap(() => {
      this.loading$.next(true);
      return this.service.getItems(this.mySelection());
    }),
    map((results: GridItem[]) => {
      results = util.convertDatesToDateOnlyStrings(results, ['month', 'dueDate']);
      this.gridData = results;
      return results;
    }),
    tap((results: GridItem[]) => {
      this.loading$.next(false);
      if (results.length == 0) {
        this.toast.error('No approved invoices. Please select an approved invoice to distribute.');
        this.closedClicked();
      }
      else {

        util.goToSavedGridScrollPos(this.fastGridEl, this.gridScrollPosition);
      }
    }),
    shareReplay(1),
    catchError(err => {
      this.loading$.next(false);
      return util.handleError(err, this.messageService)
    }), retry(3)
  )

  distributeResult$ = this.distribute$.pipe(
    switchMap(() => {
      this.loading$.next(true);
      const invoiceSelections = this.convertDistributables();
      return this.service.distribute(invoiceSelections);
    }),
    tap(response => {
      this.loading$.next(false);
      if (response.hasErrors) {
        // throw error box in the event of any errors in the interface
        this.messageService.throw(response.message);
      }
      else {
        this.messageService.info(response.message);
      }
      this.closedClicked();
    }),
    shareReplay(1),
    catchError(err => {
      this.loading$.next(false);
      return util.handleError(err, this.messageService)
    }), retry(3)
  );

  convertDistributables(): InvoiceSelection[] {
    return this.invoicesSelection = this.gridData.map(x => {
      const selection: InvoiceSelection = { id: x.id };
      return selection;
    });
  }

  closedClicked() {
    this.closed.emit();
  }

  finishDistribute() {
    this.distribute$.next(null);
  }
}
