<script>
import { GlFriendlyWrap } from '@gitlab/ui';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import SafeLink from 'ee/vue_shared/components/safe_link.vue';
import Icon from '~/vue_shared/components/icon.vue';
import ExpandButton from '~/vue_shared/components/expand_button.vue';
import SeverityBadge from './severity_badge.vue';
import getFileLocation from '../store/utils/get_file_location';
import VulnerabilityDetail from './vulnerability_detail.vue';
import { s__, sprintf } from '~/locale';
import { REPORT_TYPES } from 'ee/security_dashboard/store/constants';

export default {
  name: 'VulnerabilityDetails',
  components: {
    CodeBlock,
    ExpandButton,
    GlFriendlyWrap,
    Icon,
    SafeLink,
    SeverityBadge,
    VulnerabilityDetail,
  },
  props: {
    vulnerability: {
      type: Object,
      required: true,
    },
  },
  computed: {
    url() {
      return this.vulnerability.request?.url || getFileLocation(this.vulnerability.location);
    },
    file() {
      const file = this.vulnerability?.location?.file;

      if (!file) {
        return null;
      }

      let lineSuffix = '';
      const { start_line: startLine, end_line: endLine } = this.vulnerability.location;

      if (startLine) {
        lineSuffix += `:${startLine}`;
        if (endLine && startLine !== endLine) {
          lineSuffix += `-${endLine}`;
        }
      }

      return `${file}${lineSuffix}`;
    },
    identifiers() {
      return this.asNonEmptyListOrNull(this.vulnerability.identifiers);
    },
    className() {
      return this.vulnerability.location?.class;
    },
    methodName() {
      return this.vulnerability.location?.method;
    },
    image() {
      return this.vulnerability.location?.image;
    },
    namespace() {
      return this.vulnerability.location?.operating_system;
    },
    links() {
      return this.asNonEmptyListOrNull(this.vulnerability.links);
    },
    instances() {
      return this.asNonEmptyListOrNull(this.vulnerability.instances);
    },
    requestHeaders() {
      return this.headersToFormattedString(this.vulnerability.request?.headers);
    },
    responseHeaders() {
      return this.headersToFormattedString(this.vulnerability.response?.headers);
    },
    responseStatusCode() {
      return this.vulnerability.response?.status_code;
    },
    scannerType() {
      return REPORT_TYPES[this.vulnerability.report_type];
    },
    scannerUrl() {
      return this.vulnerability.scanner?.url || '';
    },
    scannerVersion() {
      return this.vulnerability.scanner?.version;
    },
    scannerName() {
      return this.vulnerability.scanner?.name;
    },
    scannerProvider() {
      if (!this.scannerVersion) {
        return this.scannerName;
      }

      return sprintf(s__('Vulnerability|%{scannerName} (version %{scannerVersion})'), {
        scannerName: this.scannerName,
        scannerVersion: this.scannerVersion,
      });
    },
  },
  methods: {
    hasMoreValues(index, values) {
      return index < values.length - 1;
    },
    asNonEmptyListOrNull(list) {
      return list?.length > 0 ? list : null;
    },
    headersToFormattedString(headers = []) {
      return headers.map(({ name, value }) => `${name}: ${value}`).join('\n');
    },
  },
};
</script>

<template>
  <div class="border-white mb-0 px-3">
    <vulnerability-detail
      v-if="vulnerability.description"
      :label="s__('Vulnerability|Description')"
    >
      <gl-friendly-wrap :text="vulnerability.description" />
    </vulnerability-detail>

    <vulnerability-detail v-if="vulnerability.project" :label="s__('Vulnerability|Project')">
      <safe-link ref="projectLink" :href="vulnerability.project.full_path" target="_blank">
        <gl-friendly-wrap :text="vulnerability.project.full_name" />
      </safe-link>
    </vulnerability-detail>

    <vulnerability-detail v-if="methodName" :label="s__('Vulnerability|Method')">
      <gl-friendly-wrap :text="methodName" />
    </vulnerability-detail>

    <vulnerability-detail v-if="url" :label="__('URL')">
      <safe-link ref="urlLink" :href="url" target="_blank">
        <gl-friendly-wrap :text="url" />
      </safe-link>
    </vulnerability-detail>

    <vulnerability-detail v-if="requestHeaders" :label="__('Request Headers')">
      <code-block ref="requestHeaders" :code="requestHeaders" max-height="225px" />
    </vulnerability-detail>

    <vulnerability-detail v-if="responseStatusCode" :label="__('Response Status')">
      <gl-friendly-wrap ref="responseStatusCode" :text="responseStatusCode" />
    </vulnerability-detail>

    <vulnerability-detail v-if="responseHeaders" :label="__('Response Headers')">
      <code-block ref="responseHeaders" :code="responseHeaders" max-height="225px" />
    </vulnerability-detail>

    <vulnerability-detail v-if="file" :label="s__('Vulnerability|File')">
      <safe-link
        v-if="vulnerability.blob_path"
        ref="fileLink"
        :href="vulnerability.blob_path"
        target="_blank"
      >
        <gl-friendly-wrap :text="file" />
      </safe-link>
      <gl-friendly-wrap v-else :text="file" />
    </vulnerability-detail>

    <vulnerability-detail v-if="vulnerability.evidence" :label="s__('Vulnerability|Evidence')">
      <gl-friendly-wrap :text="vulnerability.evidence" />
    </vulnerability-detail>

    <vulnerability-detail v-if="identifiers" :label="s__('Vulnerability|Identifiers')">
      <span v-for="(identifier, i) in identifiers" :key="i">
        <safe-link
          v-if="identifier.url"
          ref="identifiersLink"
          :href="identifier.url"
          target="_blank"
          rel="noopener noreferrer"
        >
          {{ identifier.name }}
        </safe-link>
        <span v-else> {{ identifier.name }} </span>
        <span v-if="hasMoreValues(i, identifiers)">,&nbsp;</span>
      </span>
    </vulnerability-detail>

    <vulnerability-detail v-if="vulnerability.severity" :label="s__('Vulnerability|Severity')">
      <severity-badge :severity="vulnerability.severity" class="d-inline" />
    </vulnerability-detail>

    <vulnerability-detail
      v-if="vulnerability.report_type"
      :label="s__('Vulnerability|Scanner Type')"
    >
      <gl-friendly-wrap :text="scannerType" />
    </vulnerability-detail>

    <vulnerability-detail v-if="scannerProvider" :label="s__('Vulnerability|Scanner Provider')">
      <safe-link ref="scannerLink" :href="scannerUrl" target="_blank" rel="noopener noreferrer">
        <gl-friendly-wrap :text="scannerProvider" />
      </safe-link>
    </vulnerability-detail>

    <vulnerability-detail v-if="className" :label="s__('Vulnerability|Class')">
      <gl-friendly-wrap :text="className" />
    </vulnerability-detail>

    <vulnerability-detail v-if="image" :label="s__('Vulnerability|Image')">
      <gl-friendly-wrap :text="image" />
    </vulnerability-detail>

    <vulnerability-detail v-if="namespace" :label="s__('Vulnerability|Namespace')">
      <gl-friendly-wrap :text="namespace" />
    </vulnerability-detail>

    <vulnerability-detail v-if="links" :label="s__('Vulnerability|Links')">
      <span v-for="(link, i) in links" :key="i">
        <safe-link ref="linksLink" :href="link.url" target="_blank" rel="noopener noreferrer">
          {{ link.value || link.url }}
        </safe-link>
        <span v-if="hasMoreValues(i, links)">,&nbsp;</span>
      </span>
    </vulnerability-detail>

    <vulnerability-detail v-if="instances" :label="s__('Vulnerability|Instances')">
      <div class="info-well">
        <ul class="report-block-list">
          <li v-for="(instance, i) in instances" :key="i" class="report-block-list-issue">
            <div class="report-block-list-icon append-right-5 failed">
              <icon :size="32" name="status_failed_borderless" />
            </div>
            <div class="report-block-list-issue-description prepend-top-5 append-bottom-5">
              <div class="report-block-list-issue-description-text">
                {{ instance.method }}
              </div>
              <div class="report-block-list-issue-description-link">
                <safe-link
                  :href="instance.uri"
                  target="_blank"
                  rel="noopener noreferrer nofollow"
                  class="break-link"
                >
                  {{ instance.uri }}
                </safe-link>
              </div>
              <expand-button v-if="instance.evidence">
                <template #expanded>
                  <pre
                    class="block report-block-dast-code prepend-top-10 report-block-issue-code"
                    v-text="instance.evidence"
                  ></pre>
                </template>
              </expand-button>
            </div>
          </li>
        </ul>
      </div>
    </vulnerability-detail>
  </div>
</template>
