<script>
import * as Sentry from '@sentry/browser';
import {
  GlAlert,
  GlBadge,
  GlIcon,
  GlLoadingIcon,
  GlSprintf,
  GlTabs,
  GlTab,
  GlButton,
  GlTable,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import alertQuery from '../graphql/queries/details.query.graphql';
import sidebarStatusQuery from '../graphql/queries/sidebar_status.query.graphql';
import { fetchPolicies } from '~/lib/graphql';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
import initUserPopovers from '~/user_popovers';
import { ALERTS_SEVERITY_LABELS, trackAlertsDetailsViewsOptions } from '../constants';
import createIssueMutation from '../graphql/mutations/create_issue_from_alert.mutation.graphql';
import toggleSidebarStatusMutation from '../graphql/mutations/toggle_sidebar_status.mutation.graphql';
import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
import Tracking from '~/tracking';
import { toggleContainerClasses } from '~/lib/utils/dom_utils';
import SystemNote from './system_notes/system_note.vue';
import AlertSidebar from './alert_sidebar.vue';
import AlertMetrics from './alert_metrics.vue';

const containerEl = document.querySelector('.page-with-contextual-sidebar');

export default {
  i18n: {
    errorMsg: s__(
      'AlertManagement|There was an error displaying the alert. Please refresh the page to try again.',
    ),
    reportedAt: s__('AlertManagement|Reported %{when}'),
    reportedAtWithTool: s__('AlertManagement|Reported %{when} by %{tool}'),
  },
  severityLabels: ALERTS_SEVERITY_LABELS,
  tabsConfig: [
    {
      id: 'overview',
      title: s__('AlertManagement|Overview'),
    },
    {
      id: 'fullDetails',
      title: s__('AlertManagement|Alert details'),
    },
    {
      id: 'metrics',
      title: s__('AlertManagement|Metrics'),
    },
  ],
  components: {
    GlBadge,
    GlAlert,
    GlIcon,
    GlLoadingIcon,
    GlSprintf,
    GlTab,
    GlTabs,
    GlButton,
    GlTable,
    TimeAgoTooltip,
    AlertSidebar,
    SystemNote,
    AlertMetrics,
  },
  inject: {
    projectPath: {
      default: '',
    },
    alertId: {
      type: String,
      default: '',
    },
    projectId: {
      type: String,
      default: '',
    },
    projectIssuesPath: {
      type: String,
      default: '',
    },
  },
  apollo: {
    alert: {
      fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
      query: alertQuery,
      variables() {
        return {
          fullPath: this.projectPath,
          alertId: this.alertId,
        };
      },
      update(data) {
        return data?.project?.alertManagementAlerts?.nodes?.[0] ?? null;
      },
      error(error) {
        this.errored = true;
        Sentry.captureException(error);
      },
    },
    sidebarStatus: {
      query: sidebarStatusQuery,
    },
  },
  data() {
    return {
      alert: null,
      errored: false,
      sidebarStatus: false,
      isErrorDismissed: false,
      createIncidentError: '',
      incidentCreationInProgress: false,
      sidebarErrorMessage: '',
    };
  },
  computed: {
    loading() {
      return this.$apollo.queries.alert.loading;
    },
    reportedAtMessage() {
      return this.alert?.monitoringTool
        ? this.$options.i18n.reportedAtWithTool
        : this.$options.i18n.reportedAt;
    },
    showErrorMsg() {
      return this.errored && !this.isErrorDismissed;
    },
    activeTab() {
      return this.$route.params.tabId || this.$options.tabsConfig[0].id;
    },
    currentTabIndex: {
      get() {
        return this.$options.tabsConfig.findIndex(tab => tab.id === this.activeTab);
      },
      set(tabIdx) {
        const tabId = this.$options.tabsConfig[tabIdx].id;
        this.$router.replace({ name: 'tab', params: { tabId } });
      },
    },
  },
  mounted() {
    this.trackPageViews();
    toggleContainerClasses(containerEl, {
      'issuable-bulk-update-sidebar': true,
      'right-sidebar-expanded': true,
    });
  },
  updated() {
    this.$nextTick(() => {
      highlightCurrentUser(this.$el.querySelectorAll('.gfm-project_member'));
      initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
    });
  },
  methods: {
    dismissError() {
      this.isErrorDismissed = true;
      this.sidebarErrorMessage = '';
    },
    toggleSidebar() {
      this.$apollo.mutate({ mutation: toggleSidebarStatusMutation });
      toggleContainerClasses(containerEl, {
        'right-sidebar-collapsed': !this.sidebarStatus,
        'right-sidebar-expanded': this.sidebarStatus,
      });
    },
    handleAlertSidebarError(errorMessage) {
      this.errored = true;
      this.sidebarErrorMessage = errorMessage;
    },
    createIncident() {
      this.incidentCreationInProgress = true;

      this.$apollo
        .mutate({
          mutation: createIssueMutation,
          variables: {
            iid: this.alert.iid,
            projectPath: this.projectPath,
          },
        })
        .then(({ data: { createAlertIssue: { errors, issue } } }) => {
          if (errors?.length) {
            [this.createIncidentError] = errors;
            this.incidentCreationInProgress = false;
          } else if (issue) {
            visitUrl(this.incidentPath(issue.iid));
          }
        })
        .catch(error => {
          this.createIncidentError = error;
          this.incidentCreationInProgress = false;
        });
    },
    incidentPath(issueId) {
      return joinPaths(this.projectIssuesPath, issueId);
    },
    trackPageViews() {
      const { category, action } = trackAlertsDetailsViewsOptions;
      Tracking.event(category, action);
    },
  },
};
</script>

<template>
  <div>
    <gl-alert v-if="showErrorMsg" variant="danger" @dismiss="dismissError">
      <p v-html="sidebarErrorMessage || $options.i18n.errorMsg"></p>
    </gl-alert>
    <gl-alert
      v-if="createIncidentError"
      variant="danger"
      data-testid="incidentCreationError"
      @dismiss="createIncidentError = null"
    >
      {{ createIncidentError }}
    </gl-alert>
    <div v-if="loading"><gl-loading-icon size="lg" class="gl-mt-5" /></div>
    <div
      v-if="alert"
      class="alert-management-details gl-relative"
      :class="{ 'pr-sm-8': sidebarStatus }"
    >
      <div
        class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-px-1 py-3 py-md-4 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-flex-direction-column gl-sm-flex-direction-row"
      >
        <div data-testid="alert-header">
          <gl-badge class="gl-mr-3">
            <strong>{{ s__('AlertManagement|Alert') }}</strong>
          </gl-badge>
          <span>
            <gl-sprintf :message="reportedAtMessage">
              <template #when>
                <time-ago-tooltip :time="alert.createdAt" />
              </template>
              <template #tool>{{ alert.monitoringTool }}</template>
            </gl-sprintf>
          </span>
        </div>
        <gl-button
          v-if="alert.issueIid"
          class="gl-mt-3 mt-sm-0 align-self-center align-self-sm-baseline alert-details-incident-button"
          data-testid="viewIncidentBtn"
          :href="incidentPath(alert.issueIid)"
          category="primary"
          variant="success"
        >
          {{ s__('AlertManagement|View incident') }}
        </gl-button>
        <gl-button
          v-else
          class="gl-mt-3 mt-sm-0 align-self-center align-self-sm-baseline alert-details-incident-button"
          data-testid="createIncidentBtn"
          :loading="incidentCreationInProgress"
          category="primary"
          variant="success"
          @click="createIncident()"
        >
          {{ s__('AlertManagement|Create incident') }}
        </gl-button>
        <gl-button
          :aria-label="__('Toggle sidebar')"
          category="primary"
          variant="default"
          class="d-sm-none gl-absolute toggle-sidebar-mobile-button"
          type="button"
          @click="toggleSidebar"
        >
          <i class="fa fa-angle-double-left"></i>
        </gl-button>
      </div>
      <div
        v-if="alert"
        class="gl-display-flex gl-justify-content-space-between gl-align-items-center"
      >
        <h2 data-testid="title">{{ alert.title }}</h2>
      </div>
      <gl-tabs v-if="alert" v-model="currentTabIndex" data-testid="alertDetailsTabs">
        <gl-tab :data-testid="$options.tabsConfig[0].id" :title="$options.tabsConfig[0].title">
          <div v-if="alert.severity" class="gl-mt-3 gl-mb-5 gl-display-flex">
            <div class="gl-font-weight-bold gl-w-13 gl-text-right gl-pr-3">
              {{ s__('AlertManagement|Severity') }}:
            </div>
            <div class="gl-pl-2" data-testid="severity">
              <span>
                <gl-icon
                  class="gl-vertical-align-middle"
                  :size="12"
                  :name="`severity-${alert.severity.toLowerCase()}`"
                  :class="`icon-${alert.severity.toLowerCase()}`"
                />
              </span>
              {{ $options.severityLabels[alert.severity] }}
            </div>
          </div>
          <div v-if="alert.startedAt" class="gl-my-5 gl-display-flex">
            <div class="gl-font-weight-bold gl-w-13 gl-text-right gl-pr-3">
              {{ s__('AlertManagement|Start time') }}:
            </div>
            <div class="gl-pl-2">
              <time-ago-tooltip data-testid="startTimeItem" :time="alert.startedAt" />
            </div>
          </div>
          <div v-if="alert.eventCount" class="gl-my-5 gl-display-flex">
            <div class="gl-font-weight-bold gl-w-13 gl-text-right gl-pr-3">
              {{ s__('AlertManagement|Events') }}:
            </div>
            <div class="gl-pl-2" data-testid="eventCount">{{ alert.eventCount }}</div>
          </div>
          <div v-if="alert.monitoringTool" class="gl-my-5 gl-display-flex">
            <div class="gl-font-weight-bold gl-w-13 gl-text-right gl-pr-3">
              {{ s__('AlertManagement|Tool') }}:
            </div>
            <div class="gl-pl-2" data-testid="monitoringTool">{{ alert.monitoringTool }}</div>
          </div>
          <div v-if="alert.service" class="gl-my-5 gl-display-flex">
            <div class="bold gl-w-13 gl-text-right gl-pr-3">
              {{ s__('AlertManagement|Service') }}:
            </div>
            <div class="gl-pl-2" data-testid="service">{{ alert.service }}</div>
          </div>
          <div v-if="alert.runbook" class="gl-my-5 gl-display-flex">
            <div class="bold gl-w-13 gl-text-right gl-pr-3">
              {{ s__('AlertManagement|Runbook') }}:
            </div>
            <div class="gl-pl-2" data-testid="runbook">{{ alert.runbook }}</div>
          </div>
          <template>
            <div v-if="alert.notes.nodes" class="issuable-discussion py-5">
              <ul class="notes main-notes-list timeline">
                <system-note v-for="note in alert.notes.nodes" :key="note.id" :note="note" />
              </ul>
            </div>
          </template>
        </gl-tab>
        <gl-tab :data-testid="$options.tabsConfig[1].id" :title="$options.tabsConfig[1].title">
          <gl-table
            class="alert-management-details-table"
            :items="[{ key: 'Value', ...alert }]"
            :show-empty="true"
            :busy="loading"
            stacked
          >
            <template #empty>
              {{ s__('AlertManagement|No alert data to display.') }}
            </template>
            <template #table-busy>
              <gl-loading-icon size="lg" color="dark" class="mt-3" />
            </template>
          </gl-table>
        </gl-tab>
        <gl-tab :data-testid="$options.tabsConfig[2].id" :title="$options.tabsConfig[2].title">
          <alert-metrics :dashboard-url="alert.metricsDashboardUrl" />
        </gl-tab>
      </gl-tabs>
      <alert-sidebar
        :alert="alert"
        @toggle-sidebar="toggleSidebar"
        @alert-error="handleAlertSidebarError"
      />
    </div>
  </div>
</template>
