# coding: utf-8

"""
    Verity471 Unified API

      - creds: 1.0.1
  - indicators: 1.0.0
  - malware: 1.0.0
  - reports: 1.0.0
  - sources: 1.0.2
  - actors: 1.0.1
  - watchers: 1.0.0
  - observables: 1.0.0
  - entities: 1.0.0
  - girs: 1.0.0


    The version of the OpenAPI document: 1.1.1
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json


from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from verity471.models.classification import Classification
from verity471.models.entities import Entities
from verity471.models.links import Links
from verity471.models.reports_victim_response import ReportsVictimResponse
from verity471.models.sources_response import SourcesResponse
from typing import Optional, Set, TYPE_CHECKING
from typing_extensions import Self

if TYPE_CHECKING:
    # Only for type checkers; does not run at runtime.
    from verity471.verity_stix import STIXMapperSettings


class SpotReportResponse(BaseModel):
    """
    Minimal schema for Spot report response with keys, types, and descriptions
    """ # noqa: E501
    body: Optional[StrictStr] = Field(default=None, description="Main content body of the report. This field may be omitted in streaming responses when content exceeds the configured maximum size; fetch full report by ID if needed.")
    classification: Classification
    creation_ts: StrictStr = Field(description="Timestamp when the report was published first time")
    entities: Optional[List[Entities]] = Field(default=None, description="List of entities mentioned in the report")
    id: StrictStr = Field(description="Unique identifier of the report")
    information_ts: StrictStr = Field(description="Timestamp of the information contained in the report")
    is_sensitive_source: Optional[StrictBool] = Field(default=None, description="Indicates if the report contains sensitive source derived information")
    is_truncated: Optional[StrictBool] = Field(default=None, description="True when the body field was omitted due to exceeding size limit; fetch full report by ID if needed")
    last_updated_ts: StrictStr = Field(description="Timestamp of last report update")
    links: Links
    released_ts: StrictStr = Field(description="Timestamp when the report was published last time")
    sources: Optional[List[SourcesResponse]] = Field(default=None, description="List of sources referenced in the report")
    title: StrictStr = Field(description="Title of the report")
    type: StrictStr = Field(description="Type of the report")
    victims: Optional[List[ReportsVictimResponse]] = Field(default=None, description="List of purported victims mentioned in the report")
    __properties: ClassVar[List[str]] = ["body", "classification", "creation_ts", "entities", "id", "information_ts", "is_sensitive_source", "is_truncated", "last_updated_ts", "links", "released_ts", "sources", "title", "type", "victims"]

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_stix(self, settings: Optional["STIXMapperSettings"] = None):
        try:
            from verity471.verity_stix.mappers.common import StixMapper
        except ImportError as e:
            raise ImportError(
                "STIX support is an optional feature. "
                "Install with: pip install 'verity471[stix]'"
            ) from e
        stix_mapper = StixMapper(settings)
        return stix_mapper.map(self.to_dict())

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of SpotReportResponse from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of classification
        if self.classification:
            _dict['classification'] = self.classification.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in entities (list)
        _items = []
        if self.entities:
            for _item_entities in self.entities:
                if _item_entities:
                    _items.append(_item_entities.to_dict())
            _dict['entities'] = _items
        # override the default output from pydantic by calling `to_dict()` of links
        if self.links:
            _dict['links'] = self.links.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in sources (list)
        _items = []
        if self.sources:
            for _item_sources in self.sources:
                if _item_sources:
                    _items.append(_item_sources.to_dict())
            _dict['sources'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in victims (list)
        _items = []
        if self.victims:
            for _item_victims in self.victims:
                if _item_victims:
                    _items.append(_item_victims.to_dict())
            _dict['victims'] = _items
        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of SpotReportResponse from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate({
            "body": obj.get("body"),
            "classification": Classification.from_dict(obj["classification"]) if obj.get("classification") is not None else None,
            "creation_ts": obj.get("creation_ts"),
            "entities": [Entities.from_dict(_item) for _item in obj["entities"]] if obj.get("entities") is not None else None,
            "id": obj.get("id"),
            "information_ts": obj.get("information_ts"),
            "is_sensitive_source": obj.get("is_sensitive_source"),
            "is_truncated": obj.get("is_truncated"),
            "last_updated_ts": obj.get("last_updated_ts"),
            "links": Links.from_dict(obj["links"]) if obj.get("links") is not None else None,
            "released_ts": obj.get("released_ts"),
            "sources": [SourcesResponse.from_dict(_item) for _item in obj["sources"]] if obj.get("sources") is not None else None,
            "title": obj.get("title"),
            "type": obj.get("type"),
            "victims": [ReportsVictimResponse.from_dict(_item) for _item in obj["victims"]] if obj.get("victims") is not None else None
        })
        return _obj


