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 { RouterLinkAction } from '@objects-view/actions/router-link-action';
import { Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { IDataField } from '@objects-view/interfaces/card-data/data-field';
import { ApiCallAction } from '@objects-view/actions/api-call-action';
import { IDetailsTab } from '@objects-view/interfaces/details/details-tab';
import { IClientModel } from '@fleio-api/client-user/model/client.model';
import { ClientsApiService } from '@fleio-api/client-user/client/clients-api.service';
import { DateFormatterPipe } from '@shared/ui/common/pipes/date-formatter.pipe';
import { CallbackAction } from '@objects-view/actions/callback-action';
import { IYesNoDialogResult } from '@shared/ui-api/interfaces/yes-no-dialog-result';
import {
  ClientDetailsEmailMessageLogComponent
} from '@shared/common-tabs/clients-users/clients/client-details-email-message-log/client-details-email-message-log.component';
import { ClientDetailsBillingComponent } from './tabs/client-details-billing/client-details-billing.component';
import { Observable } from 'rxjs';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { OrderingService } from '@shared/ui-api/ordering.service';
import { CartApiService } from '@fleio-api/billing/cart/cart-api.service';
import { CartItemsApiService } from '@fleio-api/billing/cart/cart-items-api.service';
import { EntityAuditLogComponent } from '../../common-components/entity-audit-log/entity-audit-log.component';
import { ClientDetailsOverviewComponent } from './tabs/client-details-overview/client-details-overview.component';
import { ClientDetailsInvoicesComponent } from './tabs/client-details-invoices/client-details-invoices.component';
import { ClientDetailsJournalComponent } from './tabs/client-details-journal/client-details-journal.component';
import {
  ClientDetailsOpenstackServiceComponent
} from './tabs/client-details-openstack-service/client-details-openstack-service.component';
import { ClientDetailsUsersComponent } from './tabs/client-details-users/client-details-users.component';
import {
  ClientDetailsCloudResourcesComponent
} from './tabs/client-details-cloud-resources/client-details-cloud-resources.component';
import { ClientDetailsServicesComponent } from './tabs/client-details-services/client-details-services.component';
import { ClientDetailsDomainsComponent } from './tabs/client-details-domains/client-details-domains.component';
import { ClientDetailsTicketsComponent } from './tabs/client-details-tickets/client-details-tickets.component';
import {
  ClientEditFormComponent
} from '@shared/common-tabs/clients-users/clients/client-edit-form/client-edit-form.component';
import { ClientDetailsReferralComponent } from './tabs/client-details-referral/client-details-referral.component';

export class ClientUIService extends ObjectUIServiceBase<IClientModel> {
  constructor(
    client: IClientModel, permissions: IPermissionsModel, state: string,
    private readonly router: Router,
    private readonly config: ConfigService,
    private readonly clientsApi: ClientsApiService,
    private readonly orderingService: OrderingService,
    private readonly cartApiService: CartApiService,
    private readonly cartItemsApiService: CartItemsApiService,
  ) {
    super(client, permissions, state);
    this.router = router;
    this.config = config;
    this.clientsApi = clientsApi;
  }

  getIcon(): IIcon {
    if (this.object && this.object.id) {
      return {
        name: '(avatar)',
        clientAvatar: this.object,
      };
    }
    return null;
  }

  getStatus(): IObjectStatus {
    switch (this.object.status) {
      case 'active':
        return {type: StatusType.Defined, value: StatusValue.Active};
      case 'inactive':
        return {type: StatusType.Defined, value: StatusValue.Disabled};
      case 'suspending':
        return {type: StatusType.Changing, value: StatusValue.Suspended};
      case 'suspended':
        return {type: StatusType.Defined, value: StatusValue.Suspended};
      case 'deleting':
        return {type: StatusType.Changing, value: StatusValue.Deleted};
      default:
        return {type: StatusType.None, value: StatusValue.None};
    }
  }

  getTitle(): ITitle {
    let title = this.object.name;
    let subText = '';
    if (this.object.company) {
      subText = title;
      title = this.object.company;
    }

    switch (this.state) {
      case 'details':
        return {
          text: $localize`Client ${title}`,
          subText: subText,
        };

      case 'edit':
        return {
          text: $localize`Edit ${title}`,
          subText: subText,
        };

      case 'create':
        return {
          text: $localize`Create client`,
        };

      case 'send-mass-email':
        return {
          text: $localize`Send mass email and/or panel notification message to selected clients`
        };

      default:
        return {
          text: title,
          subText: subText,
        };
    }
  }

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

    actions.push(new RouterLinkAction({
        icon: {name: 'edit', class: 'fl-icons'},
        name: $localize`Edit`,
        tooltip: $localize`Edit`,
        routerUrl: this.config.getPanelUrl(`clients-users/clients/${this.object.id}/edit`),
        router: this.router,
      }
    ));

    actions.push(new CallbackAction({
        icon: {name: 'add_shopping_cart'},
        name: $localize`Create order`,
        tooltip: $localize`Create order`,
        redirectAfterExecute: false,
        refreshAfterExecute: false,
        callback: (action) => new Observable<IActionResult>((subscriber) => {
          this.cartApiService.list().subscribe((cart: any) => {
            if (cart?.client) {
              if (cart.client.toString() === this.object.id.toString()) {
                this.router.navigateByUrl(this.config.getPanelUrl(
                  `orders/select-product?filtering=cycles__currency__code:${cart.currency}`
                )).then(() => {
                });
                subscriber.next({success: false, message: null});
                subscriber.complete();
                return;
              }
              let htmlMessage = '';
              htmlMessage += '<span>' + $localize`An order is already in progress for client:` + '</span><br>';
              htmlMessage += '<span>' + `${cart.client_data.long_name}` + '</span><br>';
              htmlMessage += '<span>' + `${cart.client_data.address1}`;
              if (cart.client_data.address2) {
                htmlMessage += `, ${cart.client_data.address2}` + '</span><br>';
              } else {
                htmlMessage += '</span><br>';
              }
              htmlMessage += '<span>' + `${cart.client_data.zip_code} ${cart.client_data.city}, ${cart.client_data.country}` + '</span>';
              action.notificationService.confirmDialog(
                {
                  title: $localize`Order already in progress`,
                  importantMessage: null,
                  htmlMessage: htmlMessage,
                  message: null,
                  secondaryMessage: $localize`Do you want to cancel the current order (shopping cart will be emptied) and start another order for ${this.object.long_name}?`,
                  yesButtonName: $localize`Start new order`,
                  noButtonName: $localize`Continue order for ${cart.client_data.long_name}`,
                }
              ).subscribe((result: IYesNoDialogResult) => {
                if (result?.button === 'yes') {
                  this.cartItemsApiService.dropCart().subscribe(() => {
                    this.router.navigateByUrl(
                      this.config.getPanelUrl(`orders/create/${this.object.id}`)
                    ).then(() => {
                    });
                  })
                  subscriber.next({success: true, message: null});
                  subscriber.complete();
                } else if (result?.button === 'no') {
                  this.router.navigateByUrl(this.config.getPanelUrl(
                    `orders/select-product?filtering=cycles__currency__code:${cart.currency}`
                  )).then(() => {
                  });
                  subscriber.next({success: true, message: null});
                  subscriber.complete();
                } else {
                  subscriber.next({success: false, message: null});
                  subscriber.complete();
                }
              });
            } else {
              this.router.navigateByUrl(
                this.config.getPanelUrl(`orders/create/${this.object.id}`),
              ).then(() => {
              });
              subscriber.next({success: true, message: null});
              subscriber.complete();
            }
          });
        })
      })
    );

    if (['active', 'suspending'].includes(this.object.status)) {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'pause'},
          name: $localize`Suspend`,
          tooltip: $localize`Suspend`,
          confirmOptions: {
            confirm: true,
            title: $localize`Suspend client`,
            message: $localize`Are you sure you want to suspend client ${this.object.name} and all associated services ?`
          },
          apiService: this.clientsApi,
          apiAction: 'suspend',
        }
      ));
    }

    if (this.object.status === 'inactive') {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'restart_alt'},
          name: $localize`Activate`,
          tooltip: $localize`Activate`,
          confirmOptions: {
            confirm: true,
            title: $localize`Activate client`,
            message: $localize`Are you sure you want to activate client ${this.object.name}? Active clients will count against license`
          },
          apiService: this.clientsApi,
          apiAction: 'activate',
        }
      ));
    }

    if (this.object.status === 'suspended') {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'play_arrow'},
          name: $localize`Resume`,
          tooltip: $localize`Resume`,
          confirmOptions: {
            confirm: true,
            title: $localize`Resume client`,
            message: $localize`Are you sure you want to resume client ${this.object.name}?`
          },
          apiService: this.clientsApi,
          apiAction: 'resume',
        }
      ));
    }

    const deleteAction = new CallbackAction({
      icon: {name: 'delete'},
      name: $localize`Delete`,
      tooltip: $localize`Delete client`,
      redirectAfterExecute: true,
      redirectUrl: this.config.getPanelUrl('clients-users/clients'),
      redirectQueryParams: this.orderingService.getQueryParams('clients-users/clients'),
      noPermissions: !this.permissions['clients.destroy'],
      callback: (action) => new Observable<IActionResult>((subscriber) => {
        action.notificationService.confirmDialog(
          {
            title: $localize`Delete client ${this.object.name}`,
            importantMessage: $localize`Warning: deleting a client will permanently delete any invoices and orders associated with the client.`,
            message: null,
            flags: [
              {
                id: 'delete-cloud-resources',
                message: $localize`Delete all services and resources (including cloud resources etc.)`,
                warningOnSelect: $localize`Warning: this will permanently delete data.`,
                selected: false,
              },
              {
                id: 'delete-exclusive-users',
                message: $localize`Delete all users that are only associated with this client`,
                warningOnSelect: null,
                selected: true,
              },
            ]
          }
        ).subscribe((result: IYesNoDialogResult) => {
          if (result?.button === 'yes') {
            this.clientsApi.delete(
              this.object.id, {
                delete_cloud_resources: result.flags['delete-cloud-resources'],
                delete_exclusive_users: result.flags['delete-exclusive-users'],
              },
            ).subscribe(() => {
              action.notificationService.showMessage($localize`Client delete scheduled`);
              subscriber.next({success: true, message: null});
              subscriber.complete();
            });
          } else {
            subscriber.next({success: false, message: null});
            subscriber.complete();
          }
        });
      })
    });

    if (this.object.suspend_instead_of_terminate) {
      deleteAction.tooltip = $localize`Delete disabled by billing settings 'suspend instead of terminate enabled' set.`;
      deleteAction.disabled = true;
    }

    actions.push(deleteAction);


    return actions;
  }

  getDetailsLink(): string {
    return this.config.getPanelUrl(`clients-users/clients/${this.object.id}`);
  }

  getCardFields(): IDataField[] {
    const datePipe = new DateFormatterPipe(this.config);
    const fields = [
      {
        name: $localize`ID`,
        value: `#${this.object.id.toString()}`,
      },
      {
        name: $localize`Created at`,
        value: `${datePipe.transform(this.object.date_created)}`,
        title: `${datePipe.getTitleAttributeValue(this.object.date_created)}`,
      }
    ];

    if (this.object.outofcredit_datetime) {
      fields.push(
        {
          name: $localize`Out of credit since`,
          value: `${datePipe.toDateTime(this.object.outofcredit_datetime)}`
        }
      );
    } else {
      fields.push(
        {
          name: $localize`Up-to-date credit`,
          value: `${this.object.uptodate_credit}`
        }
      );
    }

    return fields;
  }

  getTabs(): IDetailsTab[] {
    switch (this.state) {
      case 'details':
        const tabs: IDetailsTab[] = [
          {
            tabName: $localize`Overview`,
            tabIdentifier: 'overview',
            component: ClientDetailsOverviewComponent,
          },
          {
            tabName: $localize`Invoices`,
            tabIdentifier: 'invoices',
            component: ClientDetailsInvoicesComponent,
            featureName: 'billing.invoices'
          },
          {
            tabName: $localize`Journal`,
            tabIdentifier: 'journal',
            component: ClientDetailsJournalComponent,
            featureName: 'billing.journal',
          },
          {
            tabName: $localize`OpenStack service`,
            tabIdentifier: 'openstack-service',
            component: ClientDetailsOpenstackServiceComponent,
            featureName: 'openstack',
          },
          {
            tabName: $localize`Users`,
            tabIdentifier: 'users',
            component: ClientDetailsUsersComponent,
            featureName: 'clients&users.users'
          },
          {
            tabName: $localize`Cloud resources`,
            tabIdentifier: 'cloud-resources',
            featureName: 'openstack',
            component: ClientDetailsCloudResourcesComponent
          },
          {
            tabName: $localize`Services`,
            tabIdentifier: 'services',
            component: ClientDetailsServicesComponent,
            featureName: 'billing.services'
          },
        ];

        if (this.config.authService.userData.referrals_enabled) {
          tabs.push(
            {
              tabName: $localize`Referral`,
              tabIdentifier: 'referral',
              component: ClientDetailsReferralComponent,
            },
          );
        }

        if (this.config.authService.feature('openstack')) {
          tabs.push(
            {
              tabName: $localize`Billing history`,
              tabIdentifier: 'billing-history',
              component: ClientDetailsBillingComponent,
              featureName: 'billing.history',
            }
          );
        }

        tabs.push.apply(tabs, [{
          tabName: $localize`Domains`,
          tabIdentifier: 'domains',
          featureName: 'plugins.domains',
          component: ClientDetailsDomainsComponent,
        },
          {
            tabName: $localize`Tickets`,
            tabIdentifier: 'tickets',
            featureName: 'plugins.tickets',
            component: ClientDetailsTicketsComponent,
          },
          {
            tabName: $localize`Email log`,
            tabIdentifier: 'email-log',
            featureName: 'logger.email-message-log',
            component: ClientDetailsEmailMessageLogComponent,
          },
          {
            tabName: $localize`Audit log`,
            tabIdentifier: 'audit-log',
            component: EntityAuditLogComponent,
            featureName: 'utils.activitylog',
            data: {
              entity_type: 'client'
            }
          }
        ]);

        return tabs;
      case 'edit':
      case 'create':
        return [
          {
            tabName: $localize`Edit`,
            tabIdentifier: 'edit',
            component: ClientEditFormComponent,
          },
        ];
    }
  }

  getCardTags(): string[] {
    const tags: string[] = [];
    if (this.object.configuration_name) {
      tags.push(this.object.configuration_name);
    }
    if (this.object.status === 'suspended') {
      tags.push($localize`Suspended`);
    }
    if (this.object.status === 'suspending') {
      tags.push($localize`Suspending`);
    }

    return tags;
  }

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

    switch (this.state) {
      case 'create':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`clients-users/clients`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Create`}));
        break;
      case 'edit':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`clients-users/clients`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Save`}));
        break;
      case 'send-mass-email':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`clients-users/clients`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({name: $localize`Send mails`}));
        break;
      default:
        break;
    }

    return actions;
  }

  getObjectDetailsRefreshInterval(): number {
    switch (this.state) {
      case 'details':
        return this.config?.current?.settings?.refreshIntervals?.clientDetailsInterval;
      default:
        return null;
    }
  }
}
