# coding: utf-8

"""
    Mixpeek API

    This is the Mixpeek API, providing access to various endpoints for data processing and retrieval.

    The version of the OpenAPI document: 1.3.0
    Contact: info@mixpeek.com
    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, StrictFloat, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional, Union
from typing_extensions import Annotated
from mixpeek.models.interaction_type import InteractionType
from typing import Optional, Set
from typing_extensions import Self

class InteractionResponse(BaseModel):
    """
    Response model for a stored interaction.  Extends SearchInteraction with system-assigned fields.
    """ # noqa: E501
    feature_id: StrictStr = Field(description="ID of the document/feature that was interacted with. REQUIRED. This should be the document_id returned in retriever results. Used to track which specific items users engage with.")
    interaction_type: Annotated[List[InteractionType], Field(min_length=1)] = Field(description="List of interaction types that occurred. REQUIRED. Multiple types can be recorded simultaneously (e.g., VIEW + CLICK + LONG_VIEW for a result the user engaged with). Use the InteractionType enum values.")
    position: Annotated[int, Field(strict=True, ge=0)] = Field(description="Position in search results where interaction occurred (0-indexed). REQUIRED. Critical for Learning to Rank - helps identify position bias. E.g., position=0 means first result, position=9 means 10th result. Higher engagement at lower positions suggests higher quality.")
    metadata: Optional[Dict[str, Any]] = Field(default=None, description="Additional context about the interaction. NOT REQUIRED. Can include device, duration, viewport info, etc. Use this to enrich interaction data with application-specific context.")
    user_id: Optional[StrictStr] = Field(default=None, description="Customer's authenticated user identifier. NOT REQUIRED. Persists across sessions for long-term tracking. Enables personalization and user-specific metrics. Use your application's user ID format.")
    session_id: Optional[StrictStr] = Field(default=None, description="Temporary identifier for a single search session. NOT REQUIRED. Typically 30min-1hr duration. Tracks anonymous and authenticated users within a session. Use to group related queries and understand search journeys.")
    execution_id: Optional[StrictStr] = Field(default=None, description="ID of the retriever execution that generated these results. NOT REQUIRED but HIGHLY RECOMMENDED for training and optimization. Links the interaction back to the exact search query, pipeline configuration, and stage execution that produced the results the user saw. Essential for: fine-tuning embeddings, training rerankers, query understanding, and tracing which pipeline configs produce better user engagement. Retrieve from the retriever execution response and pass to interactions.")
    retriever_id: Optional[StrictStr] = Field(default=None, description="ID of the retriever that was executed. NOT REQUIRED but RECOMMENDED for multi-retriever analytics. Enables comparing performance across different retriever configurations. If execution_id is provided, retriever_id can be inferred from the execution record.")
    query_snapshot: Optional[Dict[str, Any]] = Field(default=None, description="Snapshot of the query input that generated these results. HIGHLY RECOMMENDED for training optimization. Storing the query directly enables 10-100x faster training data extraction by avoiding expensive joins to execution records. Use the same format as retriever query input (e.g., {'text': '...', 'filters': {...}}). Essential for: embedding fine-tuning (query-document pairs), query expansion learning, and analyzing which query patterns lead to better engagement. NOT REQUIRED but strongly recommended for production use cases involving model training.")
    document_score: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Initial retrieval score of this document when shown to the user. HIGHLY RECOMMENDED for Learning to Rank (LTR). This is a critical feature for reranker training - helps the model learn how to adjust initial scores based on user engagement. Should match the score from the retriever execution results. NOT REQUIRED but strongly recommended for LTR and reranker training.")
    result_set_size: Optional[Annotated[int, Field(strict=True, ge=1)]] = Field(default=None, description="Total number of results shown to the user in this search. NOT REQUIRED but useful for context. Helps understand interaction patterns - clicking position 5 of 10 results is different from position 5 of 100 results. Useful for position bias correction and CTR analysis.")
    interaction_id: StrictStr = Field(description="Unique identifier for this interaction record. System-assigned UUID. Use this to reference the interaction in subsequent requests.")
    timestamp: Optional[StrictStr] = Field(default=None, description="ISO 8601 timestamp when the interaction was recorded. System-assigned. Used for time-based analysis, training data recency weighting, and temporal trends in user behavior.")
    __properties: ClassVar[List[str]] = ["feature_id", "interaction_type", "position", "metadata", "user_id", "session_id", "execution_id", "retriever_id", "query_snapshot", "document_score", "result_set_size", "interaction_id", "timestamp"]

    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_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 InteractionResponse 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,
        )
        return _dict

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

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

        _obj = cls.model_validate({
            "feature_id": obj.get("feature_id"),
            "interaction_type": obj.get("interaction_type"),
            "position": obj.get("position"),
            "metadata": obj.get("metadata"),
            "user_id": obj.get("user_id"),
            "session_id": obj.get("session_id"),
            "execution_id": obj.get("execution_id"),
            "retriever_id": obj.get("retriever_id"),
            "query_snapshot": obj.get("query_snapshot"),
            "document_score": obj.get("document_score"),
            "result_set_size": obj.get("result_set_size"),
            "interaction_id": obj.get("interaction_id"),
            "timestamp": obj.get("timestamp")
        })
        return _obj


