<script>
import { GlLink, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { sum } from '~/lib/utils/number_utils';
import { isNumber } from 'lodash';
import { Accordion, AccordionItem } from 'ee/vue_shared/components/accordion';
import {
  severityGroupTypes,
  severityLevels,
  severityLevelsTranslations,
  SEVERITY_LEVELS_ORDERED_BY_SEVERITY,
  SEVERITY_GROUPS,
} from 'ee/security_dashboard/store/modules/vulnerable_projects/constants';

export default {
  css: {
    severityGroups: {
      [severityGroupTypes.F]: 'gl-text-red-900',
      [severityGroupTypes.D]: 'gl-text-red-700',
      [severityGroupTypes.C]: 'gl-text-orange-600',
      [severityGroupTypes.B]: 'gl-text-orange-400',
      [severityGroupTypes.A]: 'gl-text-green-500',
    },
    severityLevels: {
      [severityLevels.CRITICAL]: 'gl-text-red-900',
      [severityLevels.HIGH]: 'gl-text-red-700',
      [severityLevels.UNKNOWN]: 'gl-text-gray-300',
      [severityLevels.MEDIUM]: 'gl-text-orange-600',
      [severityLevels.LOW]: 'gl-text-orange-500',
      [severityLevels.NONE]: 'gl-text-green-500',
    },
  },
  accordionItemsContentMaxHeight: '445px',
  components: { Accordion, AccordionItem, GlLink, GlIcon },
  directives: {
    'gl-tooltip': GlTooltipDirective,
  },
  props: {
    helpPagePath: {
      type: String,
      required: false,
      default: '',
    },
    projects: {
      type: Array,
      required: true,
    },
  },
  computed: {
    severityGroups() {
      return SEVERITY_GROUPS.map(group => ({
        ...group,
        projects: this.findProjectsForGroup(group),
      }));
    },
  },
  methods: {
    findProjectsForGroup(group) {
      if (group.type === severityGroupTypes.A) {
        return this.projects.filter(
          project =>
            Object.values(project.vulnerabilitySeveritiesCount || {})
              .filter(i => isNumber(i))
              .reduce(sum, 0) === 0,
        );
      }

      return this.projects
        .filter(project =>
          group.severityLevels.some(level => project.vulnerabilitySeveritiesCount?.[level] > 0),
        )
        .map(project => ({
          ...project,
          mostSevereVulnerability: this.findMostSevereVulnerabilityForGroup(project, group),
        }));
    },

    findMostSevereVulnerabilityForGroup(project, group) {
      const mostSevereVulnerability = {};

      SEVERITY_LEVELS_ORDERED_BY_SEVERITY.some(level => {
        if (!group.severityLevels.includes(level)) {
          return false;
        }

        const hasVulnerabilityForThisLevel = project.vulnerabilitySeveritiesCount?.[level] > 0;

        if (hasVulnerabilityForThisLevel) {
          mostSevereVulnerability.level = level;
          mostSevereVulnerability.count = project.vulnerabilitySeveritiesCount[level];
        }

        return hasVulnerabilityForThisLevel;
      });

      return mostSevereVulnerability;
    },
    shouldAccordionItemBeDisabled({ projects }) {
      return projects?.length < 1;
    },
    cssForSeverityGroup({ type }) {
      return this.$options.css.severityGroups[type];
    },
    cssForMostSevereVulnerability({ level }) {
      return this.$options.css.severityLevels[level] || [];
    },
    severityText(severityLevel) {
      return severityLevelsTranslations[severityLevel];
    },
  },
};
</script>

<template>
  <section class="gl-border-solid gl-border-1 gl-border-gray-100 gl-rounded-base">
    <header class="gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-p-5">
      <h4 class="gl-my-0">
        {{ __('Project security status') }}
        <gl-link
          v-if="helpPagePath"
          :href="helpPagePath"
          :aria-label="__('Project security status help page')"
          target="_blank"
          ><gl-icon name="question"
        /></gl-link>
      </h4>
      <p class="gl-text-gray-700 gl-m-0">
        {{ __('Projects are graded based on the highest severity vulnerability present') }}
      </p>
    </header>
    <accordion class="gl-px-5">
      <template #default="{ accordionId }">
        <accordion-item
          v-for="severityGroup in severityGroups"
          :ref="`accordionItem${severityGroup.type}`"
          :key="severityGroup.type"
          :accordion-id="accordionId"
          :disabled="shouldAccordionItemBeDisabled(severityGroup)"
          :max-height="$options.accordionItemsContentMaxHeight"
        >
          <template #title="{ isExpanded, isDisabled }"
            ><h5 class="gl-display-flex gl-align-items-center gl-font-weight-normal gl-p-0 gl-m-0">
              <span
                v-gl-tooltip
                :title="severityGroup.description"
                class="gl-font-weight-bold gl-mr-5 gl-font-lg"
                :class="cssForSeverityGroup(severityGroup)"
              >
                {{ severityGroup.type }}
              </span>
              <span :class="{ 'gl-font-weight-bold': isExpanded, 'gl-text-gray-700': isDisabled }">
                {{ n__('%d project', '%d projects', severityGroup.projects.length) }}
              </span>
            </h5>
          </template>
          <template #subTitle>
            <p class="gl-m-0 ml-5 gl-pb-2 gl-text-gray-700">{{ severityGroup.warning }}</p>
          </template>
          <div class="gl-ml-7 gl-pb-3">
            <ul class="list-unstyled gl-py-2">
              <li v-for="project in severityGroup.projects" :key="project.id" class="gl-py-3">
                <gl-link target="_blank" :href="`/${project.fullPath}/-/security/dashboard`">{{
                  project.nameWithNamespace
                }}</gl-link>
                <span
                  v-if="project.mostSevereVulnerability"
                  ref="mostSevereCount"
                  class="d-block text-lowercase"
                  :class="cssForMostSevereVulnerability(project.mostSevereVulnerability)"
                  >{{ project.mostSevereVulnerability.count }}
                  {{ severityText(project.mostSevereVulnerability.level) }}
                </span>
              </li>
            </ul>
          </div>
        </accordion-item>
      </template>
    </accordion>
  </section>
</template>
