import { BaseAction } from './base-action';
import { Observable, of } from 'rxjs';
import { IActionResult } from '../interfaces/actions/action-result';
import { catchError, map } from 'rxjs/operators';
import { FleioApiService } from '@fleio-api/fleio-api.service';
import { IBaseFleioObjectModel } from '@fleio-api/base-model/base-fleio-object.model';
import { HttpErrorResponse } from '@angular/common/http';
import { IYesNoDialogResult } from '@shared/ui-api/interfaces/yes-no-dialog-result';

export enum CallType {
  Post,
  Delete
}

export type ApiParams = Record<string, any>

export class ApiCallAction extends BaseAction {
  apiService: FleioApiService<IBaseFleioObjectModel>;
  apiAction: string;
  apiParams: ApiParams;
  callType: CallType;
  successMessage: string;
  errorMessage: string;
  endpointIdentifier: any;
  getParamsFromDialogResult: (dialogResult?: IYesNoDialogResult) => ApiParams = (dialogResult) => {
    let params: ApiParams;
    if (dialogResult?.flags) {
      params = {...dialogResult?.flags};
    }

    return params || {};
  };

  constructor(init?: Partial<ApiCallAction>) {
    super(init);
    if (!this.callType) {
      this.callType = CallType.Post;
    }
  }

  executeImpl(dialogResult: IYesNoDialogResult): Observable<IActionResult> {
    if (!this.endpointIdentifier) {
      this.endpointIdentifier = this.object?.id;
    }

    const apiParams = {...(this.apiParams||{}), ...this.getParamsFromDialogResult(dialogResult)};

    switch (this.callType) {
      case CallType.Post:
        if (this.endpointIdentifier) {
          return this.apiService.objectPostAction(this.endpointIdentifier, this.apiAction, apiParams).pipe(
            map(response => {
              if (response.detail) {
                return {
                  success: true,
                  message: response.detail,
                };
              } else {
                console.warn('Unable to extract message from backend response');
                console.warn(response);
                return null;
              }
            })
          ).pipe(catchError((error: HttpErrorResponse) => {
            let message = error && error.error && error.error.detail ? error.error.detail : $localize`Failed to complete action`;
            message = this.errorMessage || message;
            return of({
              success: false,
              message,
            });
          }));
        } else {
          return this.apiService.postAction(this.apiAction, apiParams).pipe(
            map(response => {
              if (response.detail) {
                return {
                  success: true,
                  message: response.detail,
                };
              } else {
                console.warn('Unable to extract message from backend response');
                console.warn(response);
                return null;
              }
            })
          ).pipe(catchError((error: HttpErrorResponse) => {
            let message = error && error.error && error.error.detail ? error.error.detail : $localize`Failed to complete action`;
            message = this.errorMessage || message;
            return of({
              success: false,
              message,
            });
          }));
        }
      case CallType.Delete:
        return this.apiService.delete(this.object.id).pipe(map(() => {
          const message: string = this.successMessage || $localize`Object deleted successfully`;
          return {
            success: true,
            message,
          };
        })).pipe(catchError((error: HttpErrorResponse) => {
          let message = error && error.error && error.error.detail ? error.error.detail : $localize`Failed to delete object`;
          if (error.status === 403) {
            message = message || this.errorMessage;
          } else {
            message = this.errorMessage || message;
          }
          return of({
            success: false,
            message,
          });
        }));
      default:
        console.warn('Unsupported call type in action');
        return of({
          success: false,
          message: $localize`Unsupported call type`,
        });
    }
  }
}
