import datetime
from collections.abc import Mapping
from typing import (
    TYPE_CHECKING,
    Any,
    TypeVar,
    Union,
)
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse

from ..models.vulnerability_severity import VulnerabilitySeverity
from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.affected_component import AffectedComponent
    from ..models.component import Component
    from ..models.cwe import Cwe
    from ..models.finding_attrib import FindingAttrib
    from ..models.service_component import ServiceComponent
    from ..models.vulnerability_alias import VulnerabilityAlias


T = TypeVar("T", bound="Vulnerability")


@_attrs_define
class Vulnerability:
    """
    Attributes:
        vuln_id (str):
        source (str):
        uuid (UUID):
        friendly_vuln_id (Union[Unset, str]):
        title (Union[Unset, str]):
        sub_title (Union[Unset, str]):
        description (Union[Unset, str]):
        detail (Union[Unset, str]):
        recommendation (Union[Unset, str]):
        references (Union[Unset, str]):
        credits_ (Union[Unset, str]):
        created (Union[Unset, datetime.datetime]):
        published (Union[Unset, datetime.datetime]):
        updated (Union[Unset, datetime.datetime]):
        cwes (Union[Unset, list['Cwe']]):
        cvss_v2_base_score (Union[Unset, float]):
        cvss_v2_impact_sub_score (Union[Unset, float]):
        cvss_v2_exploitability_sub_score (Union[Unset, float]):
        cvss_v2_vector (Union[Unset, str]):
        cvss_v3_base_score (Union[Unset, float]):
        cvss_v3_impact_sub_score (Union[Unset, float]):
        cvss_v3_exploitability_sub_score (Union[Unset, float]):
        cvss_v3_vector (Union[Unset, str]):
        owasp_rr_likelihood_score (Union[Unset, float]):
        owasp_rr_technical_impact_score (Union[Unset, float]):
        owasp_rr_business_impact_score (Union[Unset, float]):
        owasp_rr_vector (Union[Unset, str]):
        severity (Union[Unset, VulnerabilitySeverity]):
        vulnerable_versions (Union[Unset, str]):
        patched_versions (Union[Unset, str]):
        epss_score (Union[Unset, float]):
        epss_percentile (Union[Unset, float]):
        components (Union[Unset, list['Component']]):
        service_components (Union[Unset, list['ServiceComponent']]):
        aliases (Union[Unset, list['VulnerabilityAlias']]):
        finding_attribution (Union[Unset, FindingAttrib]):
        affected_project_count (Union[Unset, int]):
        affected_active_project_count (Union[Unset, int]):
        affected_inactive_project_count (Union[Unset, int]):
        affected_components (Union[Unset, list['AffectedComponent']]):
        cwe (Union[Unset, Cwe]):
    """

    vuln_id: str
    source: str
    uuid: UUID
    friendly_vuln_id: Union[Unset, str] = UNSET
    title: Union[Unset, str] = UNSET
    sub_title: Union[Unset, str] = UNSET
    description: Union[Unset, str] = UNSET
    detail: Union[Unset, str] = UNSET
    recommendation: Union[Unset, str] = UNSET
    references: Union[Unset, str] = UNSET
    credits_: Union[Unset, str] = UNSET
    created: Union[Unset, datetime.datetime] = UNSET
    published: Union[Unset, datetime.datetime] = UNSET
    updated: Union[Unset, datetime.datetime] = UNSET
    cwes: Union[Unset, list["Cwe"]] = UNSET
    cvss_v2_base_score: Union[Unset, float] = UNSET
    cvss_v2_impact_sub_score: Union[Unset, float] = UNSET
    cvss_v2_exploitability_sub_score: Union[Unset, float] = UNSET
    cvss_v2_vector: Union[Unset, str] = UNSET
    cvss_v3_base_score: Union[Unset, float] = UNSET
    cvss_v3_impact_sub_score: Union[Unset, float] = UNSET
    cvss_v3_exploitability_sub_score: Union[Unset, float] = UNSET
    cvss_v3_vector: Union[Unset, str] = UNSET
    owasp_rr_likelihood_score: Union[Unset, float] = UNSET
    owasp_rr_technical_impact_score: Union[Unset, float] = UNSET
    owasp_rr_business_impact_score: Union[Unset, float] = UNSET
    owasp_rr_vector: Union[Unset, str] = UNSET
    severity: Union[Unset, VulnerabilitySeverity] = UNSET
    vulnerable_versions: Union[Unset, str] = UNSET
    patched_versions: Union[Unset, str] = UNSET
    epss_score: Union[Unset, float] = UNSET
    epss_percentile: Union[Unset, float] = UNSET
    components: Union[Unset, list["Component"]] = UNSET
    service_components: Union[Unset, list["ServiceComponent"]] = UNSET
    aliases: Union[Unset, list["VulnerabilityAlias"]] = UNSET
    finding_attribution: Union[Unset, "FindingAttrib"] = UNSET
    affected_project_count: Union[Unset, int] = UNSET
    affected_active_project_count: Union[Unset, int] = UNSET
    affected_inactive_project_count: Union[Unset, int] = UNSET
    affected_components: Union[Unset, list["AffectedComponent"]] = UNSET
    cwe: Union[Unset, "Cwe"] = UNSET
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

    def to_dict(self) -> dict[str, Any]:
        vuln_id = self.vuln_id

        source = self.source

        uuid = str(self.uuid)

        friendly_vuln_id = self.friendly_vuln_id

        title = self.title

        sub_title = self.sub_title

        description = self.description

        detail = self.detail

        recommendation = self.recommendation

        references = self.references

        credits_ = self.credits_

        created: Union[Unset, str] = UNSET
        if not isinstance(self.created, Unset):
            created = self.created.isoformat()

        published: Union[Unset, str] = UNSET
        if not isinstance(self.published, Unset):
            published = self.published.isoformat()

        updated: Union[Unset, str] = UNSET
        if not isinstance(self.updated, Unset):
            updated = self.updated.isoformat()

        cwes: Union[Unset, list[dict[str, Any]]] = UNSET
        if not isinstance(self.cwes, Unset):
            cwes = []
            for cwes_item_data in self.cwes:
                cwes_item = cwes_item_data.to_dict()
                cwes.append(cwes_item)

        cvss_v2_base_score = self.cvss_v2_base_score

        cvss_v2_impact_sub_score = self.cvss_v2_impact_sub_score

        cvss_v2_exploitability_sub_score = self.cvss_v2_exploitability_sub_score

        cvss_v2_vector = self.cvss_v2_vector

        cvss_v3_base_score = self.cvss_v3_base_score

        cvss_v3_impact_sub_score = self.cvss_v3_impact_sub_score

        cvss_v3_exploitability_sub_score = self.cvss_v3_exploitability_sub_score

        cvss_v3_vector = self.cvss_v3_vector

        owasp_rr_likelihood_score = self.owasp_rr_likelihood_score

        owasp_rr_technical_impact_score = self.owasp_rr_technical_impact_score

        owasp_rr_business_impact_score = self.owasp_rr_business_impact_score

        owasp_rr_vector = self.owasp_rr_vector

        severity: Union[Unset, str] = UNSET
        if not isinstance(self.severity, Unset):
            severity = self.severity.value

        vulnerable_versions = self.vulnerable_versions

        patched_versions = self.patched_versions

        epss_score = self.epss_score

        epss_percentile = self.epss_percentile

        components: Union[Unset, list[dict[str, Any]]] = UNSET
        if not isinstance(self.components, Unset):
            components = []
            for components_item_data in self.components:
                components_item = components_item_data.to_dict()
                components.append(components_item)

        service_components: Union[Unset, list[dict[str, Any]]] = UNSET
        if not isinstance(self.service_components, Unset):
            service_components = []
            for service_components_item_data in self.service_components:
                service_components_item = service_components_item_data.to_dict()
                service_components.append(service_components_item)

        aliases: Union[Unset, list[dict[str, Any]]] = UNSET
        if not isinstance(self.aliases, Unset):
            aliases = []
            for aliases_item_data in self.aliases:
                aliases_item = aliases_item_data.to_dict()
                aliases.append(aliases_item)

        finding_attribution: Union[Unset, dict[str, Any]] = UNSET
        if not isinstance(self.finding_attribution, Unset):
            finding_attribution = self.finding_attribution.to_dict()

        affected_project_count = self.affected_project_count

        affected_active_project_count = self.affected_active_project_count

        affected_inactive_project_count = self.affected_inactive_project_count

        affected_components: Union[Unset, list[dict[str, Any]]] = UNSET
        if not isinstance(self.affected_components, Unset):
            affected_components = []
            for affected_components_item_data in self.affected_components:
                affected_components_item = affected_components_item_data.to_dict()
                affected_components.append(affected_components_item)

        cwe: Union[Unset, dict[str, Any]] = UNSET
        if not isinstance(self.cwe, Unset):
            cwe = self.cwe.to_dict()

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "vulnId": vuln_id,
                "source": source,
                "uuid": uuid,
            }
        )
        if friendly_vuln_id is not UNSET:
            field_dict["friendlyVulnId"] = friendly_vuln_id
        if title is not UNSET:
            field_dict["title"] = title
        if sub_title is not UNSET:
            field_dict["subTitle"] = sub_title
        if description is not UNSET:
            field_dict["description"] = description
        if detail is not UNSET:
            field_dict["detail"] = detail
        if recommendation is not UNSET:
            field_dict["recommendation"] = recommendation
        if references is not UNSET:
            field_dict["references"] = references
        if credits_ is not UNSET:
            field_dict["credits"] = credits_
        if created is not UNSET:
            field_dict["created"] = created
        if published is not UNSET:
            field_dict["published"] = published
        if updated is not UNSET:
            field_dict["updated"] = updated
        if cwes is not UNSET:
            field_dict["cwes"] = cwes
        if cvss_v2_base_score is not UNSET:
            field_dict["cvssV2BaseScore"] = cvss_v2_base_score
        if cvss_v2_impact_sub_score is not UNSET:
            field_dict["cvssV2ImpactSubScore"] = cvss_v2_impact_sub_score
        if cvss_v2_exploitability_sub_score is not UNSET:
            field_dict["cvssV2ExploitabilitySubScore"] = (
                cvss_v2_exploitability_sub_score
            )
        if cvss_v2_vector is not UNSET:
            field_dict["cvssV2Vector"] = cvss_v2_vector
        if cvss_v3_base_score is not UNSET:
            field_dict["cvssV3BaseScore"] = cvss_v3_base_score
        if cvss_v3_impact_sub_score is not UNSET:
            field_dict["cvssV3ImpactSubScore"] = cvss_v3_impact_sub_score
        if cvss_v3_exploitability_sub_score is not UNSET:
            field_dict["cvssV3ExploitabilitySubScore"] = (
                cvss_v3_exploitability_sub_score
            )
        if cvss_v3_vector is not UNSET:
            field_dict["cvssV3Vector"] = cvss_v3_vector
        if owasp_rr_likelihood_score is not UNSET:
            field_dict["owaspRRLikelihoodScore"] = owasp_rr_likelihood_score
        if owasp_rr_technical_impact_score is not UNSET:
            field_dict["owaspRRTechnicalImpactScore"] = owasp_rr_technical_impact_score
        if owasp_rr_business_impact_score is not UNSET:
            field_dict["owaspRRBusinessImpactScore"] = owasp_rr_business_impact_score
        if owasp_rr_vector is not UNSET:
            field_dict["owaspRRVector"] = owasp_rr_vector
        if severity is not UNSET:
            field_dict["severity"] = severity
        if vulnerable_versions is not UNSET:
            field_dict["vulnerableVersions"] = vulnerable_versions
        if patched_versions is not UNSET:
            field_dict["patchedVersions"] = patched_versions
        if epss_score is not UNSET:
            field_dict["epssScore"] = epss_score
        if epss_percentile is not UNSET:
            field_dict["epssPercentile"] = epss_percentile
        if components is not UNSET:
            field_dict["components"] = components
        if service_components is not UNSET:
            field_dict["serviceComponents"] = service_components
        if aliases is not UNSET:
            field_dict["aliases"] = aliases
        if finding_attribution is not UNSET:
            field_dict["findingAttribution"] = finding_attribution
        if affected_project_count is not UNSET:
            field_dict["affectedProjectCount"] = affected_project_count
        if affected_active_project_count is not UNSET:
            field_dict["affectedActiveProjectCount"] = affected_active_project_count
        if affected_inactive_project_count is not UNSET:
            field_dict["affectedInactiveProjectCount"] = affected_inactive_project_count
        if affected_components is not UNSET:
            field_dict["affectedComponents"] = affected_components
        if cwe is not UNSET:
            field_dict["cwe"] = cwe

        return field_dict

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.affected_component import AffectedComponent
        from ..models.component import Component
        from ..models.cwe import Cwe
        from ..models.finding_attrib import FindingAttrib
        from ..models.service_component import ServiceComponent
        from ..models.vulnerability_alias import VulnerabilityAlias

        d = dict(src_dict)
        vuln_id = d.pop("vulnId")

        source = d.pop("source")

        uuid = UUID(d.pop("uuid"))

        friendly_vuln_id = d.pop("friendlyVulnId", UNSET)

        title = d.pop("title", UNSET)

        sub_title = d.pop("subTitle", UNSET)

        description = d.pop("description", UNSET)

        detail = d.pop("detail", UNSET)

        recommendation = d.pop("recommendation", UNSET)

        references = d.pop("references", UNSET)

        credits_ = d.pop("credits", UNSET)

        _created = d.pop("created", UNSET)
        created: Union[Unset, datetime.datetime]
        if isinstance(_created, Unset):
            created = UNSET
        else:
            created = isoparse(_created)

        _published = d.pop("published", UNSET)
        published: Union[Unset, datetime.datetime]
        if isinstance(_published, Unset):
            published = UNSET
        else:
            published = isoparse(_published)

        _updated = d.pop("updated", UNSET)
        updated: Union[Unset, datetime.datetime]
        if isinstance(_updated, Unset):
            updated = UNSET
        else:
            updated = isoparse(_updated)

        cwes = []
        _cwes = d.pop("cwes", UNSET)
        for cwes_item_data in _cwes or []:
            cwes_item = Cwe.from_dict(cwes_item_data)

            cwes.append(cwes_item)

        cvss_v2_base_score = d.pop("cvssV2BaseScore", UNSET)

        cvss_v2_impact_sub_score = d.pop("cvssV2ImpactSubScore", UNSET)

        cvss_v2_exploitability_sub_score = d.pop("cvssV2ExploitabilitySubScore", UNSET)

        cvss_v2_vector = d.pop("cvssV2Vector", UNSET)

        cvss_v3_base_score = d.pop("cvssV3BaseScore", UNSET)

        cvss_v3_impact_sub_score = d.pop("cvssV3ImpactSubScore", UNSET)

        cvss_v3_exploitability_sub_score = d.pop("cvssV3ExploitabilitySubScore", UNSET)

        cvss_v3_vector = d.pop("cvssV3Vector", UNSET)

        owasp_rr_likelihood_score = d.pop("owaspRRLikelihoodScore", UNSET)

        owasp_rr_technical_impact_score = d.pop("owaspRRTechnicalImpactScore", UNSET)

        owasp_rr_business_impact_score = d.pop("owaspRRBusinessImpactScore", UNSET)

        owasp_rr_vector = d.pop("owaspRRVector", UNSET)

        _severity = d.pop("severity", UNSET)
        severity: Union[Unset, VulnerabilitySeverity]
        if isinstance(_severity, Unset):
            severity = UNSET
        else:
            severity = VulnerabilitySeverity(_severity)

        vulnerable_versions = d.pop("vulnerableVersions", UNSET)

        patched_versions = d.pop("patchedVersions", UNSET)

        epss_score = d.pop("epssScore", UNSET)

        epss_percentile = d.pop("epssPercentile", UNSET)

        components = []
        _components = d.pop("components", UNSET)
        for components_item_data in _components or []:
            components_item = Component.from_dict(components_item_data)

            components.append(components_item)

        service_components = []
        _service_components = d.pop("serviceComponents", UNSET)
        for service_components_item_data in _service_components or []:
            service_components_item = ServiceComponent.from_dict(
                service_components_item_data
            )

            service_components.append(service_components_item)

        aliases = []
        _aliases = d.pop("aliases", UNSET)
        for aliases_item_data in _aliases or []:
            aliases_item = VulnerabilityAlias.from_dict(aliases_item_data)

            aliases.append(aliases_item)

        _finding_attribution = d.pop("findingAttribution", UNSET)
        finding_attribution: Union[Unset, FindingAttrib]
        if isinstance(_finding_attribution, Unset):
            finding_attribution = UNSET
        else:
            finding_attribution = FindingAttrib.from_dict(_finding_attribution)

        affected_project_count = d.pop("affectedProjectCount", UNSET)

        affected_active_project_count = d.pop("affectedActiveProjectCount", UNSET)

        affected_inactive_project_count = d.pop("affectedInactiveProjectCount", UNSET)

        affected_components = []
        _affected_components = d.pop("affectedComponents", UNSET)
        for affected_components_item_data in _affected_components or []:
            affected_components_item = AffectedComponent.from_dict(
                affected_components_item_data
            )

            affected_components.append(affected_components_item)

        _cwe = d.pop("cwe", UNSET)
        cwe: Union[Unset, Cwe]
        if isinstance(_cwe, Unset):
            cwe = UNSET
        else:
            cwe = Cwe.from_dict(_cwe)

        vulnerability = cls(
            vuln_id=vuln_id,
            source=source,
            uuid=uuid,
            friendly_vuln_id=friendly_vuln_id,
            title=title,
            sub_title=sub_title,
            description=description,
            detail=detail,
            recommendation=recommendation,
            references=references,
            credits_=credits_,
            created=created,
            published=published,
            updated=updated,
            cwes=cwes,
            cvss_v2_base_score=cvss_v2_base_score,
            cvss_v2_impact_sub_score=cvss_v2_impact_sub_score,
            cvss_v2_exploitability_sub_score=cvss_v2_exploitability_sub_score,
            cvss_v2_vector=cvss_v2_vector,
            cvss_v3_base_score=cvss_v3_base_score,
            cvss_v3_impact_sub_score=cvss_v3_impact_sub_score,
            cvss_v3_exploitability_sub_score=cvss_v3_exploitability_sub_score,
            cvss_v3_vector=cvss_v3_vector,
            owasp_rr_likelihood_score=owasp_rr_likelihood_score,
            owasp_rr_technical_impact_score=owasp_rr_technical_impact_score,
            owasp_rr_business_impact_score=owasp_rr_business_impact_score,
            owasp_rr_vector=owasp_rr_vector,
            severity=severity,
            vulnerable_versions=vulnerable_versions,
            patched_versions=patched_versions,
            epss_score=epss_score,
            epss_percentile=epss_percentile,
            components=components,
            service_components=service_components,
            aliases=aliases,
            finding_attribution=finding_attribution,
            affected_project_count=affected_project_count,
            affected_active_project_count=affected_active_project_count,
            affected_inactive_project_count=affected_inactive_project_count,
            affected_components=affected_components,
            cwe=cwe,
        )

        vulnerability.additional_properties = d
        return vulnerability

    @property
    def additional_keys(self) -> list[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties
