import { ObjectUIServiceBase } from '@objects-view/object-ui-service-base';
import { IJournalEntryModel } from '@fleio-api/billing/model/journal-entry.model';
import { Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { JournalsApiService } from '@fleio-api/billing/journal/journal-api.service';
import { MatDialog } from '@angular/material/dialog';
import { GatewayApiService } from '@fleio-api/billing/gateways/gateway-api.service';
import { NotificationService } from '@shared/ui-api/notification.service';
import { IPermissionsModel } from '@fleio-api/base-model/IPermissionsModel';
import { IIcon } from '@shared/ui/common/interfaces/icon';
import { IObjectStatus, StatusType, StatusValue } from '@objects-view/interfaces/object-status';
import { ITitle } from '@objects-view/interfaces/card-data/card-title';
import { IAction } from '@objects-view/interfaces/actions/action';
import { CallbackAction } from '@objects-view/actions/callback-action';
import { of } from 'rxjs';
import { ApiCallAction, CallType } from '@objects-view/actions/api-call-action';
import { IDataField } from '@objects-view/interfaces/card-data/data-field';
import { IDetailsTab } from '@objects-view/interfaces/details/details-tab';
import { RouterLinkAction } from '@objects-view/actions/router-link-action';
import { JournalEditFormComponent } from './tabs/server-edit-form/journal-edit-form.component';
import { JournalEditTrackerService } from './journal-edit-tracker.service';
import { JournalDetailsOverviewComponent } from './tabs/journal-details-overview/journal-details-overview.component';


export class JournalUiService extends ObjectUIServiceBase<IJournalEntryModel> {
  protected readonly router: Router;
  protected readonly config: ConfigService;
  protected readonly journalsApiService: JournalsApiService;
  protected readonly matDialog: MatDialog;
  protected readonly gatewayApiService: GatewayApiService;
  protected readonly notificationService: NotificationService;

  constructor(
    journal: IJournalEntryModel, permissions: IPermissionsModel, state: string,
    router: Router, config: ConfigService, journalsApiService: JournalsApiService, matDialog: MatDialog,
    gatewayApiService: GatewayApiService, notificationService: NotificationService,
    private journalEditTrackerService: JournalEditTrackerService,
  ) {
    super(journal, permissions, state);
    this.matDialog = matDialog;
    this.router = router;
    this.config = config;
    this.journalsApiService = journalsApiService;
    this.gatewayApiService = gatewayApiService;
    this.notificationService = notificationService;
  }

  getIcon(): IIcon {
    return null;
  }

  getStatus(): IObjectStatus {
    return {type: StatusType.None, value: StatusValue.None};
  }

  getTitle(): ITitle {
    switch (this.state) {
      case 'details':
        return {
          text: $localize`Journal details`
        };
      case 'edit':
        return {
          text: $localize`Edit journal entry`
        };
      default:
        return {
          text: `${this.object.id}`,
        };
    }
  }

  getActions(): IAction[] {
    const actions: IAction[] = [];

    if (this.object && this.object.transaction && this.object.transaction.actions &&
      Array.isArray(this.object.transaction.actions)) {
      for (const action of this.object.transaction.actions) {
        let actionIcon = 'play_arrow';
        if (action.name === 'refund') {
          actionIcon = 'undo';
        }
        if (action.redirect) {
          actions.push(new CallbackAction(
            {
              object: this.object,
              icon: {name: actionIcon},
              tooltip: action.display,
              name: action.name,
              callback: () => {
                if (action.name === 'capture') {
                  this.config.authService.generateOtpToken().subscribe(token => {
                    const query = `fleio-token=${token}&invoice=${this.object.invoice}&transaction=${this.object.transaction.id}`;
                    let redirectUrl = this.config.getPanelApiUrl('billing/gateway/');
                    redirectUrl += action.gateway + '/' + action.name + '?' + query;
                    window.location.href = redirectUrl;
                  });
                } else {
                  this.notificationService.confirmDialog(
                    {
                      title: $localize`${action.display} transaction`,
                      message: $localize`Do you want to ${action.display.toLowerCase()} transaction?`
                    }
                  ).subscribe(result => {
                    if (result?.button === 'yes') {
                      this.config.authService.generateOtpToken().subscribe(token => {
                        const query = `fleio-token=${token}&invoice=${this.object.invoice}&transaction=${this.object.transaction.id}`;
                        let redirectUrl = this.config.getPanelApiUrl('billing/gateway/');
                        redirectUrl += action.gateway + '/' + action.name + '?' + query;
                        window.location.href = redirectUrl;
                      });
                    }
                  });
                }
                return of(null);
              }
            }
          ));
        } else {
          actions.push(new ApiCallAction({
            icon: {name: actionIcon},
            tooltip: action.display,
            name: action.name,
            confirmOptions: {
              confirm: true,
              title: $localize`${action.display} transaction`,
              message: $localize`Do you want to ${action.display.toLowerCase()} transaction?`,
            },
            object: this.object,
            apiService: this.gatewayApiService,
            callType: CallType.Post,
            apiAction: action.name,
            endpointIdentifier: action.gateway,
            apiParams: {
              invoice: this.object.invoice,
              transaction: this.object.transaction.id
            },
          }));
        }
      }
    }

    actions.push(new RouterLinkAction({
      icon: {name: 'edit'},
      name: $localize`Edit`,
      tooltip: $localize`Edit journal entry`,
      routerUrl: this.config.getPanelUrl(`billing/journal/${this.object.id}/edit`),
      noPermissions: !this.permissions['journal.update'],
      router: this.router,
    }))

    let deleteRedirectUrl = this.config.getCurrentUrl()

    if (deleteRedirectUrl.includes('billing/journal') && deleteRedirectUrl.length > 'billing/journal'.length) {
      deleteRedirectUrl = this.config.getPanelUrl('billing/journal');
    } else {
      deleteRedirectUrl = null;
    }

    actions.push(new ApiCallAction({
      object: this.object,
      icon: {name: 'delete'},
      name: $localize`Delete`,
      tooltip: $localize`Delete journal entry`,
      refreshAfterExecute: true,
      redirectAfterExecute: !!deleteRedirectUrl,
      redirectUrl: deleteRedirectUrl,
      confirmOptions: {
        confirm: true,
        title: $localize`Delete journal entry`,
        message: $localize`Are you sure you want to delete journal entry ${this.object.id}?`,
        importantMessage: $localize`Deleting journal entry reverses any related credit added to client balance and/or paid invoice.`,
        noButtonName: $localize`Cancel`,
        yesButtonName: $localize`Delete`,
      },
      apiService: this.journalsApiService,
      callType: CallType.Delete,
      noPermissions: !this.permissions['journal.destroy'],
      postExecuteCallback: () => {
        // service cycles may have changed, ensure they refresh
        this.journalEditTrackerService.notifyJournalChange()
      }
    }));

    return actions;
  }

  getDetailsLink(): string {
    return this.config.getPanelUrl(`billing/journal/${this.object.id}`);
  }

  getCardFields(): IDataField[] {
    return [];
  }

  getTabs(): IDetailsTab[] {
    switch (this.state) {
      case 'details':
        return [
          {
            tabName: $localize`Overview`,
            tabIdentifier: 'overview',
            component: JournalDetailsOverviewComponent
          }
        ];
      case 'edit':
        return [
          {
            tabName: $localize`Edit`,
            tabIdentifier: 'edit',
            component: JournalEditFormComponent,
          }
        ];
      default:
        return [];
    }
  }

  getCardTags(): string[] {
    return [];
  }

  getDetailsActions(): IAction[] {
    const actions = [];

    switch (this.state) {
      case 'edit':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`billing/journal`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Save`}));
        break;
      default:
        break;
    }

    return actions;
  }

  getObjectDetailsRefreshInterval(): number {
    switch (this.state) {
      case 'details':
        return this.config.getDefaultRefreshInterval(true);
      default:
        return null;
    }
  }
}
