import { Injectable } from '@angular/core';
import { Actions, Store, ofActionDispatched } from '@ngxs/store';
import {
  DeleteRemissionShippingDocument,
  RequestDeleteShippingDocument,
  ResetRemissionState,
  RequestUpdateRemissionFilter,
  SetRemissionFilter,
  UpdateShippingDocuent,
  SetRemissionProcess,
  SetRemissionShippingDocument,
} from '../actions/remission.actions';
import {
  flatMap,
  filter,
  map,
  catchError,
  switchMap,
  first,
  withLatestFrom,
  take,
} from 'rxjs/operators';
import { RemissionService, RemissionProcess } from '@isa/remission';
import { of } from 'rxjs';
import { ResetBreadcrumbsTo } from '../actions/breadcrumb.actions';
import { SetBranchProcessCurrentPath } from '../actions/branch-process.actions';
import { Router } from '@angular/router';

@Injectable({ providedIn: 'root' })
export class RemissionStateHandler {
  constructor(
    private actions$: Actions,
    private store: Store,
    private remissionService: RemissionService,
    private router: Router
  ) {
    this.registerHandlers();
  }

  private registerHandlers() {
    this.requestDeleteShippingDocumentListener();
    this.updateRemissionFilter();
    this.updateShippingDocument();
  }

  private updateShippingDocument() {
    this.actions$
      .pipe(ofActionDispatched(UpdateShippingDocuent))
      .pipe(
        switchMap((action: UpdateShippingDocuent) =>
          this.remissionService
            .getRemission({
              remissionProcessId: action.remissionProcessId,
            })
            .pipe(take(1))
        )
      )
      .subscribe((process) => {
        const activeShippingDocument = process.shippingDocuments.find(
          (document) => !document.isCompleted
        );

        if (activeShippingDocument) {
          this.store.dispatch(
            new SetRemissionShippingDocument(activeShippingDocument)
          );
        }

        return this.store.dispatch(new SetRemissionProcess(process));
      });
  }

  private updateRemissionFilter() {
    this.actions$
      .pipe(ofActionDispatched(RequestUpdateRemissionFilter))
      .pipe(
        switchMap((action: RequestUpdateRemissionFilter) => {
          return this.remissionService
            .updateRemissionFilter({
              remissionProcessId: action.remissionProcessId,
              changes: action.filter,
            })
            .pipe(
              map((updatedFilter) => ({
                remissionProcessId: action.remissionProcessId,
                filter: updatedFilter,
              })),
              withLatestFrom(
                this.remissionService.getRemission({
                  remissionProcessId: action.remissionProcessId,
                })
              ),
              first()
            );
        })
      )
      .subscribe(([result, process]) => {
        this.store.dispatch(
          new SetRemissionFilter(result.remissionProcessId, result.filter)
        );
        this.store.dispatch(new SetRemissionProcess(process));
      });
  }

  private requestDeleteShippingDocumentListener() {
    this.actions$
      .pipe(ofActionDispatched(RequestDeleteShippingDocument))
      .pipe(
        map((action: RequestDeleteShippingDocument) => action.remissionProcess),
        filter(
          (action) =>
            !!action.shippingDocuments && !!action.shippingDocuments[0]
        ),
        flatMap((action: RemissionProcess) =>
          this.remissionService
            .deleteShippingDocument({
              remissionProcessId: action.id,
              externalId: action.externalId,
              shippingDocumentId:
                action.shippingDocuments &&
                action.shippingDocuments[0] &&
                action.shippingDocuments[0].id,
            })
            .pipe(
              filter(
                (response) => !!response.result && response.result.deleted
              ),
              map((_) => action.id),
              catchError((err) => {
                console.error(err);

                return of(action.id);
              })
            )
        )
      )
      .subscribe((remissionProcessId) => {
        this.store.dispatch(
          new DeleteRemissionShippingDocument(remissionProcessId)
        );
        this.store.dispatch(new ResetRemissionState());
        this.navigateToStartPage();
      });
  }

  // TODO Refactor to create Router Service to handle all routings in app
  private navigateToStartPage() {
    const path = '/remission/create';
    this.store.dispatch(
      new ResetBreadcrumbsTo(
        {
          path: path,
          name: 'Remission',
        },
        'remission'
      )
    );

    this.router
      .navigate([path])
      .then((_) =>
        this.store.dispatch(new SetBranchProcessCurrentPath(path, true))
      );
  }
}
