import { IPermissionsModel } from '@fleio-api/base-model/IPermissionsModel';
import { IIcon } from '@shared/ui/common/interfaces/icon';
import { ITitle } from '@objects-view/interfaces/card-data/card-title';
import { IObjectStatus, StatusType, StatusValue } from '@objects-view/interfaces/object-status';
import { ObjectUIServiceBase } from '@objects-view/object-ui-service-base';
import { IAction } from '@objects-view/interfaces/actions/action';
import { ActivatedRoute, Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { IDataField } from '@objects-view/interfaces/card-data/data-field';
import { IDetailsTab } from '@objects-view/interfaces/details/details-tab';
import { MatDialog } from '@angular/material/dialog';
import { ProductGroupsApiService } from '@fleio-api/billing/product-groups/product-groups-api.service';
import { IProductGroupModel } from '@fleio-api/billing/model/product-group.model';
import { RouterLinkAction } from '@objects-view/actions/router-link-action';
import { ApiCallAction, CallType } from '@objects-view/actions/api-call-action';
import { IProductModel } from '@fleio-api/billing/model/product.model';
import { CallbackAction } from '@objects-view/actions/callback-action';
import { map } from 'rxjs/operators';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { ProductsApiService } from '@fleio-api/billing/products/product-api.service';
import { Observable } from 'rxjs';
import { ActivityLogListUiService } from '../../utils/activity-log/activity-log-list-ui.service';
import { EntityAuditLogComponent } from '../../common-components/entity-audit-log/entity-audit-log.component';
import { ProductEditFormComponent } from './tabs/product-edit-form/product-edit-form.component';
import { ProductDetailsOverviewComponent } from './tabs/product-details-overview/product-details-overview.component';
import { ProductDetailsConfOptsComponent } from './tabs/product-details-conf-opts/product-details-conf-opts.component';
import { ProductDetailsUpgradesComponent } from './tabs/product-details-upgrades/product-details-upgrades.component';
import { ProductLinksComponent } from './tabs/product-links/product-links.component';
import { ProductGroupEditFormComponent } from './dialogs/product-group-edit-form/product-group-edit-form.component';
import { ProductCycleEditFormComponent } from './dialogs/product-cycle-edit-form/product-cycle-edit-form.component';

export class ProductUIService extends ObjectUIServiceBase<IProductGroupModel & IProductModel> {
  private readonly router: Router;
  private readonly config: ConfigService;
  private readonly productGroupsApiService: ProductGroupsApiService;
  private readonly matDialog: MatDialog;
  private readonly productsApiService: ProductsApiService;
  private readonly activatedRoute: ActivatedRoute;

  constructor(
    object: IProductGroupModel & IProductModel, permissions: IPermissionsModel, state: string,
    router: Router, config: ConfigService, productGroupsApiService: ProductGroupsApiService, matDialog: MatDialog,
    productsApiService: ProductsApiService, activatedRoute: ActivatedRoute,
  ) {
    super(object, permissions, state);
    this.matDialog = matDialog;
    this.router = router;
    this.config = config;
    this.productGroupsApiService = productGroupsApiService;
    this.productsApiService = productsApiService;
    this.activatedRoute = activatedRoute;
  }

  getIcon(): IIcon {
    return null;
  }

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

  getTitle(): ITitle {
    switch (this.state) {
      case 'create':
        return {
          text: $localize`Create product`
        };
      case 'edit':
        return {
          text: $localize`Edit product`
        };
      default:
        return {
          text: `${this.object.name}`,
          subText: `${this.object.description} (${this.object.status})`
        };
    }
  }

  getActions(): IAction[] {
    const actions: IAction[] = [];
    switch (this.state) {
      case 'table-view':
        actions.push(new CallbackAction({
          tooltip: $localize`Edit product group`,
          icon: {name: 'edit'},
          name: $localize`Edit product group`,
          noPermissions: !this.permissions['productgroups.update'],
          callback: () => this.matDialog.open(
            ProductGroupEditFormComponent, {
              data: {productGroup: this.object},
              autoFocus: false,
            }).afterClosed().pipe(map(result => {
            if (result === 'true' || result === true) {
              const queryParams = {};
              Object.assign(queryParams, this.activatedRoute.snapshot.queryParams);
              this.router.navigate([], {
                relativeTo: this.activatedRoute,
                queryParams
              }).catch(() => {
                // error has to be handled by interceptor, or where the request is done
              });
            }
            return {message: result} as IActionResult;
          }))
        }));
        let deleteGroupTooltip = $localize`Delete product group`;
        if (this.object && this.object.products && this.object.products.length) {
          deleteGroupTooltip = $localize`Cannot delete group while\nit contains products`;
        }
        actions.push(new ApiCallAction(
          {
            object: this.object,
            icon: {name: 'delete'},
            tooltip: deleteGroupTooltip,
            name: $localize`Delete`,
            confirmOptions: {
              confirm: true,
              title: $localize`Delete product group`,
              message: $localize`Are you sure you want to delete product group ${this.object.name}?`,
            },
            noPermissions: !this.permissions['productgroups.destroy'],
            apiService: this.productGroupsApiService,
            successMessage: $localize`Product group deleted`,
            errorMessage: $localize`Failed to delete product group, check logs for details`,
            callType: CallType.Delete,
            refreshAfterExecute: false,
            redirectAfterExecute: true,
            redirectUrl: this.config.getPanelUrl('billing/products'),
            disabled: !!(this.object && this.object.products && this.object.products.length)
          }));
        break;
      case 'details':
        actions.push(new RouterLinkAction({
          icon: {name: 'edit'},
          name: $localize`Edit`,
          tooltip: $localize`Edit product`,
          noPermissions: !this.permissions['products.update'],
          routerUrl: this.config.getPanelUrl(`billing/products/${this.object.id}/edit`),
          router: this.router,
        }));

        let addCycleTooltip = $localize`Add cycle`;
        if (this.object.billing_type === 'onetime') {
          addCycleTooltip = $localize`Add price`;
        }

        actions.push(new CallbackAction(
          {
            object: this.object,
            tooltip: addCycleTooltip,
            icon: {name: 'playlist_add'},
            name: addCycleTooltip,
            redirectAfterExecute: true,
            redirectUrl: this.config.getPanelUrl(`billing/products/${this.object.id}`),
            callback: () => new Observable<IActionResult>((subscriber) => {
              this.matDialog.open(
                ProductCycleEditFormComponent, {
                  data: {product: this.object},
                  autoFocus: false,
                }).afterClosed().subscribe(result => {
                subscriber.next({success: !!result, message: null});
                subscriber.complete();
              });
            }),
          }
        ));

        actions.push(new ApiCallAction(
          {
            object: this.object,
            icon: {name: 'delete'},
            tooltip: $localize`Delete product`,
            name: $localize`Delete`,
            confirmOptions: {
              confirm: true,
              title: $localize`Delete product`,
              message: $localize`Are you sure you want to delete product ${this.object.name}?`,
            },
            noPermissions: !this.permissions['products.destroy'],
            apiService: this.productsApiService,
            successMessage: $localize`Product deleted`,
            callType: CallType.Delete,
            refreshAfterExecute: false,
            redirectAfterExecute: true,
            redirectUrl: this.config.getPanelUrl('billing/products'),
          }));
        break;
      default:
        break;
    }
    return actions;
  }

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

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

  getTabs(): IDetailsTab[] {
    switch (this.state) {
      case 'create':
        return [
          {
            component: ProductEditFormComponent,
            tabName: $localize`Create`,
            tabIdentifier: 'create',
          }
        ];
      case 'edit':
        return [
          {
            component: ProductEditFormComponent,
            tabName: $localize`Edit`,
            tabIdentifier: 'edit',
          }
        ];
      case 'details':
        const detailsTabs = [
          {
            component: ProductDetailsOverviewComponent,
            tabName: $localize`Overview`,
            tabIdentifier: 'overview',
          },
          {
            component: ProductDetailsConfOptsComponent,
            tabName: $localize`Configurable options`,
            tabIdentifier: 'configurable-options',
          },
        ];

        if (this.object.billing_type !== 'onetime') {
         detailsTabs.push({
            component: ProductDetailsUpgradesComponent,
            tabName: $localize`Upgrades`,
            tabIdentifier: 'upgrades',
          } as IDetailsTab);
        }

        detailsTabs.push.apply(detailsTabs, [
          {
            component: ProductLinksComponent,
            tabName: $localize`Product links`,
            tabIdentifier: 'product-links',
          },
          {
            tabName: $localize`Audit log`,
            tabIdentifier: 'audit-log',
            component: EntityAuditLogComponent,
            featureName: 'utils.activitylog',
            data: {
              entity_type: 'product'
            },
          }
        ]);
        return detailsTabs;
      default:
        return [];
    }
  }

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

  getDetailsActions(): IAction[] {
    const actions = [];
    switch (this.state) {
      case 'create':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`billing/products`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Save`}));
        break;
      case 'edit':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`billing/products`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Save`}));
        break;
      default:
        break;
    }
    return actions;
  }
}
