import { Router } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { ITicketModel } from '@fleio-api/plugins/tickets/model/ticket.model';
import { ObjectUIServiceBase } from '@objects-view/object-ui-service-base';
import { ConfigService } from '@shared/config/config.service';
import { TicketsApiService } from '@fleio-api/plugins/tickets/tickets-api.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 { RouterLinkAction } from '@objects-view/actions/router-link-action';
import { IDataField } from '@objects-view/interfaces/card-data/data-field';
import { IDetailsTab } from '@objects-view/interfaces/details/details-tab';
import { CallbackAction } from '@objects-view/actions/callback-action';
import { TicketsUtilsService } from '@fleio-api/plugins/tickets/tickets-utils.service';
import { ApiCallAction, CallType } from '@objects-view/actions/api-call-action';
import { TicketLinkDialogComponent } from './dialogs/ticket-link-dialog/ticket-link-dialog.component';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { map } from 'rxjs/operators';
import { TicketEditSignaturesFormComponent } from './tabs/ticket-edit-signatures-form/ticket-edit-signatures-form.component';
import { TicketMergeDialogComponent } from './dialogs/ticket-merge-dialog/ticket-merge-dialog.component';
import { TicketDetailsTabComponent } from '@shared/plugins/common-tabs/tickets/ticket-details-tab/ticket-details-tab.component';
import { TicketsOpenNewTabComponent } from './tabs/tickets-open-new-tab/tickets-open-new-tab.component';
import { TicketEditFormComponent } from './tabs/ticket-edit-form/ticket-edit-form.component';
import {
  UserTicketNotificationsSettingsFormComponent
} from './tabs/user-ticket-notifications-settings-form/user-ticket-notifications-settings-form.component';
import { AppColor } from '@shared/ui/common/enums/app-color.enum';
import { TicketRowType } from './ticket-row-type.enum';
import { CloseTicketDialogComponent } from './dialogs/close-ticket-dialog/close-ticket-dialog.component';
import { RefreshService } from '@shared/ui-api/refresh.service';
import { EntityAuditLogComponent } from '../../common-components/entity-audit-log/entity-audit-log.component';

export class TicketUiService extends ObjectUIServiceBase<ITicketModel> {
  private readonly ticketsUtilsService: TicketsUtilsService;
  public static getTicketStatus(object: ITicketModel, rowType?: TicketRowType): {
    type: StatusType;
    value: StatusValue;
    statusArrow?: {
      color: AppColor;
      direction: string;
      position?: string;
      right?: string;
    };
  } {
    if (object && object.status) {
      let statusArrow = null;
      switch (object.priority) {
        case 'high':
          statusArrow = {
            color: AppColor.Red,
            direction: 'up',
            position: rowType ? 'absolute' : null,
            right: rowType ? '-9px' : null,
          };
          break;
        case 'low':
          statusArrow = {
            color: AppColor.Yellow,
            direction: 'down',
            position: rowType ? 'absolute' : null,
            right: rowType ? '-9px' : null,
          };
          break;
      }
      switch (object.status) {
        case 'open':
          return {type: StatusType.Defined, value: StatusValue.Waiting, statusArrow};
        case 'on hold':
          return {type: StatusType.Defined, value: StatusValue.Warning, statusArrow};
        case 'in progress':
          return {type: StatusType.Defined, value: StatusValue.Error, statusArrow};
        case 'done':
        case 'merged':
          return {type: StatusType.Defined, value: StatusValue.Disabled, statusArrow};
        case 'answered':
          return {type: StatusType.Defined, value: StatusValue.Active, statusArrow};
        case 'customer reply':
          return {type: StatusType.Defined, value: StatusValue.Waiting, statusArrow};
      }
    }
    return {type: StatusType.None, value: StatusValue.None};
  }


  constructor(
    ticket: ITicketModel, permissions: IPermissionsModel, state: string,
    private readonly router: Router,
    private config: ConfigService,
    private readonly ticketsApiService: TicketsApiService,
    private matDialog: MatDialog,
    private refreshService: RefreshService,
  ) {
    super(ticket, permissions, state);
    this.matDialog = matDialog;
    this.router = router;
    this.config = config;
    this.ticketsApiService = ticketsApiService;
    this.ticketsUtilsService = new TicketsUtilsService();
  }

  getIcon(): IIcon {
    return null;
  }

  getStatus(params?: {rowType: TicketRowType}): IObjectStatus {
    return TicketUiService.getTicketStatus(this.object, params?.rowType);
  }

  getTitle(): ITitle {
    switch (this.state) {
      case 'user-signatures':
        return {
          text: $localize`Edit signatures`
        };
      case 'details':
        return {
          text: $localize`#${this.object.id} - ${this.object.title}`,
          textAsHtml: true,
          subText: $localize`Status: ${this.object.status_display}`
        };
      case 'open-new-ticket':
        return {
          text: $localize`Open a new ticket`,
        };
      case 'user-notifications-settings':
        return {
          text: $localize`Edit ticket notifications settings`,
        };
      default:
        return {
          text: $localize`#${this.object.id} - ${this.object.title}`,
          textAsHtml: true,
          subText: $localize`Priority: ${this.object.priority_display}`,
          textBold: this.object.unread
        };
    }
  }

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

    if (!this.object.pinned_by_current_user) {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'push_pin'},
          name: $localize`Pin ticket`,
          tooltip: $localize`Pin ticket`,
          confirmOptions: {
            confirm: true,
            title: $localize`Pin ticket`,
            message: $localize`Mark ticket as pinned?`,
          },
          apiService: this.ticketsApiService,
          apiAction: 'mark_as_pinned',
        }
      ));
    } else {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {
            name: 'push_pin',
            class: 'rotate-45',
          },
          name: $localize`Unpin ticket`,
          tooltip: $localize`Unpin ticket`,
          confirmOptions: {
            confirm: true,
            title: $localize`Unpin ticket`,
            message: $localize`Unpin ticket?`,
          },
          apiService: this.ticketsApiService,
          apiAction: 'unpin',
        }
      ));
    }

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

    if (!this.object.unread) {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'markunread'},
          name: $localize`Mark as unread`,
          tooltip: $localize`Mark as unread`,
          confirmOptions: {
            confirm: true,
            title: $localize`Mark as unread`,
            message: $localize`Mark as unread?`,
          },
          apiService: this.ticketsApiService,
          apiAction: 'mark_as_unread',
        }
      ));
    }

    if (this.object.unread) {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'markunread'},
          name: $localize`Mark as read`,
          tooltip: $localize`Mark as read`,
          confirmOptions: {
            confirm: true,
            title: $localize`Mark as read`,
            message: $localize`Mark as read?`,
          },
          apiService: this.ticketsApiService,
          apiAction: 'mark_as_read',
        }
      ));
    }

    if (this.object.status !== 'in progress' && this.object.status !== 'done') {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'play_arrow'},
          name: $localize`Set in progress`,
          tooltip: $localize`Set in progress`,
          confirmOptions: {
            confirm: true,
            title: $localize`Set in progress`,
            message: $localize`Set in progress?`,
          },
          apiService: this.ticketsApiService,
          apiAction: 'set_in_progress',
        }
      ));
    }

    if (this.object.status !== 'on hold' && this.object.status !== 'done') {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'stop'},
          name: $localize`Set on hold`,
          tooltip: $localize`Set on hold`,
          confirmOptions: {
            confirm: true,
            title: $localize`Set on hold`,
            message: $localize`Set on hold?`,
          },
          apiService: this.ticketsApiService,
          apiAction: 'set_on_hold',
        }
      ));
    }

    if (this.object.status !== 'done') {
      actions.push(new CallbackAction(
        {
          object: this.object,
          icon: {name: 'lock'},
          name: $localize`Close ticket`,
          tooltip: $localize`Close ticket`,
          callback: () => this.matDialog.open(
            CloseTicketDialogComponent, {
              data: {ticket: this.object},
              autoFocus: false,
            }).afterClosed().pipe(map(result => {
            if (!result) {
              return;
            }
            this.refreshService.refresh();
            return {message: result} as IActionResult;
          }))
        }
      ));
    }

    if (this.object.status === 'done') {
      actions.push(new ApiCallAction(
        {
          object: this.object,
          icon: {name: 'lock_open'},
          name: $localize`Reopen ticket`,
          tooltip: $localize`Reopen ticket`,
          confirmOptions: {
            confirm: true,
            title: $localize`Reopen ticket`,
            message: $localize`Reopen ticket?`,
          },
          apiService: this.ticketsApiService,
          apiAction: 'reopen_ticket',
        }
      ));
    }

    actions.push(new CallbackAction(
      {
        object: this.object,
        icon: {name: 'playlist_add'},
        tooltip: $localize`Link a ticket`,
        name: $localize`Link a ticket`,
        callback: () => this.matDialog.open(
            TicketLinkDialogComponent, {
              data: {ticket: this.object},
              autoFocus: false,
          }).afterClosed().pipe(map(result => {
            if (!result) {
              return ;
            }
            this.router.navigateByUrl(
              this.config.getPanelUrl(`tickets/${this.object.id}`)
            ).catch();
            return {message: result} as IActionResult;
          }))
      }
    ));

    actions.push(new CallbackAction(
      {
        object: this.object,
        icon: {name: 'call_merge'},
        tooltip: $localize`Merge a ticket`,
        name: $localize`Merge a ticket`,
        callback: () => this.matDialog.open(
            TicketMergeDialogComponent, {
              data: {ticket: this.object},
              autoFocus: false,
          }).afterClosed().pipe(map(result => {
            if (!result) {
              return ;
            }
            this.router.navigateByUrl(
              this.config.getPanelUrl(`tickets/${this.object.id}`)
            ).catch();
            return {message: result} as IActionResult;
          }))
      }
    ));

    const deleteActionParams = {
      object: this.object,
      icon: {name: 'delete'},
      name: $localize`Delete`,
      tooltip: $localize`Delete`,
      confirmOptions: {
        confirm: true,
        title: $localize`Delete ticket`,
        message: $localize`Are you sure you want to delete ticket #${this.object.id}?`,
      },
      successMessage: $localize`Ticket deleted`,
      errorMessage: $localize`Failed to delete ticked, check logs for details`,
      apiService: this.ticketsApiService,
      callType: CallType.Delete,
    } as any;

    if (this.state === 'table-view') {
      deleteActionParams.refreshAfterExecute = true;
    } else {
      deleteActionParams.refreshAfterExecute = false;
      deleteActionParams.redirectAfterExecute = true;
      deleteActionParams.redirectUrl = this.config.getPanelUrl('tickets');
    }

    actions.push(new ApiCallAction(deleteActionParams));

    return actions;
  }

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

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

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

  getTabs(): IDetailsTab[] {
    switch (this.state) {
      case 'open-new-ticket':
        return [
          {
            tabName: $localize`Open new ticket`,
            tabIdentifier: 'open-new-ticket',
            component: TicketsOpenNewTabComponent,
          },
        ];
      case 'details':
        return [
          {
            tabName: $localize`Details`,
            tabIdentifier: 'details',
            component: TicketDetailsTabComponent,
          },
          {
            tabName: $localize`Audit log`,
            tabIdentifier: 'audit-log',
            component: EntityAuditLogComponent,
            featureName: 'utils.activitylog',
            data: {
              entity_type: 'ticket'
            },
            hideActions: true,
          }
        ];
      case 'edit':
        return [
          {
            tabName: $localize`Edit`,
            tabIdentifier: 'edit',
            component: TicketEditFormComponent,
          }
        ];
      case 'user-signatures':
        return [
          {
            tabName: $localize`Signatures`,
            tabIdentifier: 'signatures',
            component: TicketEditSignaturesFormComponent
          }
        ];
      case 'user-notifications-settings':
        return [
          {
            tabName: $localize`Notifications settings`,
            tabIdentifier: 'notifications-settings',
            component: UserTicketNotificationsSettingsFormComponent,
          }
        ];
      default:
        return [];
    }
  }

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

    switch (this.state) {
      case 'open-new-ticket':
        actions.push(new CallbackAction({ name: $localize`Open ticket` }));
        break;
      case 'user-signatures':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPrevUrl(`user/profile`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({
          name: $localize`Add signature`,
          internalName: 'Add signature',
        }));
        actions.push(new CallbackAction({
          name: $localize`Save`,
          primary: true,
        }));
        break;
      case 'user-notifications-settings':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPanelUrl(`user/profile`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({ name: $localize`Save` }));
        break;
      case 'edit':
        actions.push(new RouterLinkAction({
            name: $localize`Cancel`,
            routerUrl: this.config.getPanelUrl(`tickets/${this.object.id}`),
            router: this.router,
          }
        ));
        actions.push(new CallbackAction({ name: $localize`Save` }));
        break;
      case 'details':
        actions.push(new CallbackAction({ name: $localize`Add note ...` }));
        actions.push(new CallbackAction({
          name: $localize`Reply & close`,
          internalName: 'reply_and_close'
        }));
        actions.push(new CallbackAction({ name: $localize`Reply` }));
        break;
      default:
        break;
    }

    return actions;
  }
}
