"""
This module defines the EnisaVulnerability class, which represents a single vulnerability in the ENISA format.
"""

import datetime
from typing import Any

from pydantic import Field

from euvd.models._basevulnerability import _BaseVulnerability
from euvd.models.advisory import Advisory
from euvd.models.basescore import BaseScore
from euvd.models.customfieldtypes import EUVDIdType
from euvd.models.enisaidproductref import EnisaIdProductRef
from euvd.models.enisaidvendorref import EnisaIdVendorRef
from euvd.models.enisaidvulnerabilityref import EnisaIdVulnerabilityRef


class EnisaVulnerability(_BaseVulnerability):
    """
    Represents a single entry in a vulnerabilities listing.
    """

    id: EUVDIdType

    vulnerabilities: set[EnisaIdVulnerabilityRef] = Field(default_factory=set)
    advisories: set[Advisory] = Field(default_factory=set)

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "EnisaVulnerability":
        """
        Parses a vulnerability dictionary into an EnisaVulnerability instance.

        Args:
            data (dict[str, Any]): The vulnerability data to parse.

        Returns:
            EnisaVulnerability: An instance of the EnisaVulnerability class.

        Raises:
            ValueError: If parsing fails due to invalid data.
        """
        try:
            return EnisaVulnerability(
                id=data["id"],
                description=data["description"],
                date_published=datetime.datetime.strptime(
                    data["datePublished"],
                    "%b %d, %Y, %I:%M:%S %p",
                ),
                date_updated=datetime.datetime.strptime(
                    data["dateUpdated"],
                    "%b %d, %Y, %I:%M:%S %p",
                ),
                base_score=BaseScore(
                    score=data.get("baseScore", 0.0),
                    version=data.get("baseScoreVersion", "2"),
                    vector=data.get("baseScoreVector"),
                )
                if data.get("baseScore", -1.0) >= 0
                else None,
                references=set(filter(None, data.get("references", "").strip().split("\n"))),
                aliases=set(filter(None, data.get("aliases", "").strip().split("\n"))),
                assigner=data["assigner"],
                epss=data.get("epss"),
                products=set(map(EnisaIdProductRef.from_dict, data.get("enisaIdProduct", []))),
                vendors=set(map(EnisaIdVendorRef.from_dict, data.get("enisaIdVendor", []))),
                vulnerabilities=set(map(EnisaIdVulnerabilityRef.from_dict, data.get("enisaIdVulnerability", []))),
                advisories=set(map(Advisory.from_dict, data.get("enisaIdAdvisory", []))),
            )
        except Exception as e:
            raise ValueError(f"Failed to parse vulnerability: {data}") from e


__all__ = [
    "EnisaVulnerability",
]
