# frozen_string_literal: true

module Enums
  module Vulnerability
    CONFIDENCE_LEVELS = {
      # undefined: 0, no longer applicable
      ignore: 1,
      unknown: 2,
      experimental: 3,
      low: 4,
      medium: 5,
      high: 6,
      confirmed: 7
    }.with_indifferent_access.freeze

    REPORT_TYPES = {
      sast: 0,
      secret_detection: 4
    }.with_indifferent_access.freeze

    SEVERITY_LEVELS = {
      # undefined: 0, no longer applicable
      info: 1,
      unknown: 2,
      # experimental: 3, formerly used by confidence, no longer applicable
      low: 4,
      medium: 5,
      high: 6,
      critical: 7
    }.with_indifferent_access.freeze

    DETECTION_METHODS = {
      gitlab_security_report: 0,
      external_security_report: 1,
      bug_bounty: 2,
      code_review: 3,
      security_audit: 4
    }.with_indifferent_access.freeze

    # keep the order of the values in the state enum, it is used in state_order method
    # to properly order vulnerabilities based on state remember to recreate
    # index_vulnerabilities_on_state_case_id index when you update or extend this enum
    VULNERABILITY_STATES = {
      detected: 1,
      confirmed: 4,
      resolved: 3,
      dismissed: 2
    }.with_indifferent_access.freeze

    OWASP_TOP_10_BY_YEAR = {
      '2017' => {
        "A1:2017-Injection" => 1,
        "A2:2017-Broken Authentication" => 2,
        "A3:2017-Sensitive Data Exposure" => 3,
        "A4:2017-XML External Entities (XXE)" => 4,
        "A5:2017-Broken Access Control" => 5,
        "A6:2017-Security Misconfiguration" => 6,
        "A7:2017-Cross-Site Scripting (XSS)" => 7,
        "A8:2017-Insecure Deserialization" => 8,
        "A9:2017-Using Components with Known Vulnerabilities" => 9,
        "A10:2017-Insufficient Logging & Monitoring" => 10
      },
      '2021' => {
        # 2021 switched to zero-padded identifiers, previous mapping is temporary
        # to be fixed with https://gitlab.com/gitlab-org/gitlab/-/issues/429565
        "A1:2021-Broken Access Control" => 11,
        "A01:2021-Broken Access Control" => 11,
        "A2:2021-Cryptographic Failures" => 12,
        "A02:2021-Cryptographic Failures" => 12,
        "A3:2021-Injection" => 13,
        "A03:2021-Injection" => 13,
        "A4:2021-Insecure Design" => 14,
        "A04:2021-Insecure Design" => 14,
        "A5:2021-Security Misconfiguration" => 15,
        "A05:2021-Security Misconfiguration" => 15,
        "A6:2021-Vulnerable and Outdated Components" => 16,
        "A06:2021-Vulnerable and Outdated Components" => 16,
        "A7:2021-Identification and Authentication Failures" => 17,
        "A07:2021-Identification and Authentication Failures" => 17,
        "A8:2021-Software and Data Integrity Failures" => 18,
        "A08:2021-Software and Data Integrity Failures" => 18,
        "A9:2021-Security Logging and Monitoring Failures" => 19,
        "A09:2021-Security Logging and Monitoring Failures" => 19,
        "A10:2021-Server-Side Request Forgery" => 20
      },
      '2025' => {
        "A01:2025-Broken Access Control" => 21,
        "A02:2025-Security Misconfiguration" => 22,
        "A03:2025-Software Supply Chain Failures" => 23,
        "A04:2025-Cryptographic Failures" => 24,
        "A05:2025-Injection" => 25,
        "A06:2025-Insecure Design" => 26,
        "A07:2025-Authentication Failures" => 27,
        "A08:2025-Software or Data Integrity Failures" => 28,
        "A09:2025-Security Logging and Alerting Failures" => 29,
        "A10:2025-Mishandling of Exceptional Conditions" => 30
      }
    }.freeze

    OWASP_TOP_10 = OWASP_TOP_10_BY_YEAR.values.inject(&:merge).with_indifferent_access.freeze

    OWASP_CATEGORIES = OWASP_TOP_10.keys.map { |key| key.split(':').first }.uniq.freeze

    OWASP_YEARS = OWASP_TOP_10_BY_YEAR.keys.freeze

    REPORT_TYPE_FEATURE_CATEGORIES = {
      sast: 'static_application_security_testing',
      secret_detection: 'secret_detection'
    }.freeze

    def self.confidence_levels
      CONFIDENCE_LEVELS
    end

    def self.parse_confidence_level(input)
      input&.downcase.then { |value| confidence_levels.key?(value) ? value : 'unknown' }
    end

    def self.report_types
      REPORT_TYPES
    end

    def self.severity_levels
      SEVERITY_LEVELS
    end

    def self.parse_severity_level(input)
      input&.downcase.then { |value| severity_levels.key?(value) ? value : 'unknown' }
    end

    def self.detection_methods
      DETECTION_METHODS
    end

    def self.vulnerability_states
      VULNERABILITY_STATES
    end

    def self.owasp_top_10
      OWASP_TOP_10
    end

    def self.owasp_categories
      OWASP_CATEGORIES
    end

    def self.owasp_years
      OWASP_YEARS
    end

    def self.report_type_feature_categories
      REPORT_TYPE_FEATURE_CATEGORIES
    end
  end
end

Enums::Vulnerability.prepend_mod_with('Enums::Vulnerability')
