from dataclasses import dataclass, field
from datetime import datetime
from typing import List

from py_mdr.ocsf_models.events import CategoryUID, ClassUID, ConfidenceID, SeverityID, StatusID
from py_mdr.ocsf_models.events.base_event import BaseEvent
from py_mdr.ocsf_models.events.findings import ActivityID
from py_mdr.ocsf_models.objects.enrichment import Enrichment
from py_mdr.ocsf_models.objects.finding_info import FindingInformation
from py_mdr.ocsf_models.objects.metadata import Metadata
from py_mdr.ocsf_models.objects.observable import Observable
from py_mdr.ocsf_models.objects.resource_details import ResourceDetails
from py_mdr.ocsf_models.objects.vulnerability_details import VulnerabilityDetails


@dataclass
class VulnerabilityFinding(BaseEvent):
    """
    The Vulnerability Finding event is a notification about weakness in an information system, system security
    procedures, internal controls, or implementation that could be exploited or triggered by a threat source.

    Activity (activity_name) [optional]: The finding activity name, as defined by the activity_id.
    Activity ID (activity_id) [required]: The normalized identifier of the finding activity.
    Affected Resources (resources) [recommended]: Describes details about the resource/resources that are affected by the vulnerability/vulnerabilities.
    Category (category_name) [optional]: The event category name, as defined by category_uid value: Findings.
    Category ID (category_uid) [required]: The category unique identifier of the event.
    Class (class_name) [optional]: The event class name, as defined by class_uid value: Vulnerability Finding.
    Class ID (class_uid) [required]: The unique identifier of a class.
    Comment (comment) [optional]: A user provided comment about the finding.
    Confidence (confidence) [optional]: The confidence, normalized to the caption of the confidence_id value.
    Confidence ID (confidence_id) [recommended]: The normalized confidence refers to the accuracy of the rule that created the finding.
    Confidence Score (confidence_score) [optional]: The confidence score as reported by the event source.
    Count (count) [optional]: The number of times that events in the same logical group occurred during the event Start Time to End Time period.
    Duration Milliseconds (duration) [optional]: The event duration or aggregate time, the amount of time the event covers from start_time to end_time in milliseconds.
    End Time (end_time) [optional]: The time of the most recent event included in the finding.
    Enrichments (enrichments) [optional]: The additional information from an external data source, which is associated with the event or a finding.
    Event Time (time) [required]: The normalized event occurrence time or the finding creation time.
    Finding Information (finding_info) [required]: Describes the supporting information about a generated finding.
    Message (message) [recommended]: The description of the event/finding, as defined by the source.
    Metadata (metadata) [required]: The metadata associated with the event or a finding.
    Observables (observables) [recommended]: The observables associated with the event or a finding.
    Raw Data (raw_data) [optional]: The raw event/finding data as received from the source.
    Resource (resource) [recommended]: Describes details about the resource that is affected by the vulnerability/vulnerabilities.
    Severity (severity) [optional]: The event/finding severity, normalized to the caption of the severity_id value.
    Severity ID (severity_id) [required]: The normalized identifier of the event/finding severity.
    Start Time (start_time) [optional]: The time of the least recent event included in the finding.
    Status (status) [optional]: The normalized status of the Finding set by the consumer normalized to the caption of the status_id value.
    Status Code (status_code) [recommended]: The event status code, as reported by the event source.
    Status Detail (status_detail) [recommended]: The status detail contains additional information about the event/finding outcome.
    Status ID (status_id) [recommended]: The normalized status identifier of the Finding, set by the consumer.
    Timezone Offset (timezone_offset) [recommended]: The number of minutes that the reported event time is ahead or behind UTC, in the range -1,080 to +1,080.
    Type ID (type_uid) [required]: The event/finding type ID.
    Type Name (type_name) [optional]: The event/finding type name, as defined by the type_uid.
    Unmapped Data (unmapped) [optional]: The attributes that are not mapped to the event schema.
    Vulnerabilities (vulnerabilities) [required]: This object describes vulnerabilities reported in a security finding.
    """
    activity_name: str = None
    activity_id: ActivityID = None
    resources: List[ResourceDetails] = field(default_factory=list)
    category_name: str = field(default=CategoryUID.Findings.name)
    category_uid: CategoryUID = field(default=CategoryUID.Findings)
    class_name: str = field(default=ClassUID.VulnerabilityFinding.name)
    class_uid: CategoryUID = field(default=ClassUID.VulnerabilityFinding)
    comment: str = None
    confidence: str = None
    confidence_id: ConfidenceID = None
    confidence_score: int = None
    count: int = None
    duration: int = None
    end_time: datetime = None
    enrichments: List[Enrichment] = field(default_factory=list)
    time: datetime = None
    finding_info: FindingInformation = field(default_factory=FindingInformation)
    message: str = None
    metadata: Metadata = field(default_factory=Metadata)
    observables: List[Observable] = field(default_factory=list)
    raw_data: str = None
    severity: str = None
    severity_id: SeverityID = None
    start_time: datetime = None
    status: str = None
    status_code: str = None
    status_detail: str = None
    status_id: StatusID = None
    timezone_offset: int = None
    # TODO: Add calculation for type uid (class_uid * 100 + activity_id)
    type_uid: int = None
    type_name: str = None
    unmapped: object = None
    vulnerabilities: List[VulnerabilityDetails] = field(default_factory=list)
