from __future__ import annotations

import datetime
from collections.abc import Mapping
from typing import TYPE_CHECKING, Any, TypeVar, cast
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.evaluation_run_status import EvaluationRunStatus
from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.evaluation_run_public_score_components_summary_type_0 import (
        EvaluationRunPublicScoreComponentsSummaryType0,
    )
    from ..models.evaluation_run_public_service_versions_type_0 import EvaluationRunPublicServiceVersionsType0


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


@_attrs_define
class EvaluationRunPublic:
    """Public representation of an evaluation run.

    Attributes:
        eval_run_id (UUID): Unique identifier for this run
        agent_version_id (UUID): Agent version being evaluated
        suite_id (int): Suite ID
        validator_hotkey (str): Validator performing evaluation
        status (EvaluationRunStatus): Status of an evaluation run through its lifecycle.
        claimed_at (datetime.datetime): When the run was claimed
        lease_expires_at (datetime.datetime): Lease expiration
        is_included (bool): Whether run is included in aggregate
        last_heartbeat_at (datetime.datetime | None | Unset): Last heartbeat
        completed_at (datetime.datetime | None | Unset): Completion timestamp
        invalidated_at (datetime.datetime | None | Unset): When run was invalidated
        invalidated_by (None | str | Unset): Who invalidated the run
        invalidation_reason (None | str | Unset): Reason for invalidation
        validator_score (float | None | Unset): Score on success
        score_components_summary (EvaluationRunPublicScoreComponentsSummaryType0 | None | Unset): Score breakdown on
            success
        service_versions (EvaluationRunPublicServiceVersionsType0 | None | Unset): Snapshot of validator service
            versions at claim time
    """

    eval_run_id: UUID
    agent_version_id: UUID
    suite_id: int
    validator_hotkey: str
    status: EvaluationRunStatus
    claimed_at: datetime.datetime
    lease_expires_at: datetime.datetime
    is_included: bool
    last_heartbeat_at: datetime.datetime | None | Unset = UNSET
    completed_at: datetime.datetime | None | Unset = UNSET
    invalidated_at: datetime.datetime | None | Unset = UNSET
    invalidated_by: None | str | Unset = UNSET
    invalidation_reason: None | str | Unset = UNSET
    validator_score: float | None | Unset = UNSET
    score_components_summary: EvaluationRunPublicScoreComponentsSummaryType0 | None | Unset = UNSET
    service_versions: EvaluationRunPublicServiceVersionsType0 | None | Unset = UNSET
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

    def to_dict(self) -> dict[str, Any]:
        from ..models.evaluation_run_public_score_components_summary_type_0 import (
            EvaluationRunPublicScoreComponentsSummaryType0,
        )
        from ..models.evaluation_run_public_service_versions_type_0 import EvaluationRunPublicServiceVersionsType0

        eval_run_id = str(self.eval_run_id)

        agent_version_id = str(self.agent_version_id)

        suite_id = self.suite_id

        validator_hotkey = self.validator_hotkey

        status = self.status.value

        claimed_at = self.claimed_at.isoformat()

        lease_expires_at = self.lease_expires_at.isoformat()

        is_included = self.is_included

        last_heartbeat_at: None | str | Unset
        if isinstance(self.last_heartbeat_at, Unset):
            last_heartbeat_at = UNSET
        elif isinstance(self.last_heartbeat_at, datetime.datetime):
            last_heartbeat_at = self.last_heartbeat_at.isoformat()
        else:
            last_heartbeat_at = self.last_heartbeat_at

        completed_at: None | str | Unset
        if isinstance(self.completed_at, Unset):
            completed_at = UNSET
        elif isinstance(self.completed_at, datetime.datetime):
            completed_at = self.completed_at.isoformat()
        else:
            completed_at = self.completed_at

        invalidated_at: None | str | Unset
        if isinstance(self.invalidated_at, Unset):
            invalidated_at = UNSET
        elif isinstance(self.invalidated_at, datetime.datetime):
            invalidated_at = self.invalidated_at.isoformat()
        else:
            invalidated_at = self.invalidated_at

        invalidated_by: None | str | Unset
        if isinstance(self.invalidated_by, Unset):
            invalidated_by = UNSET
        else:
            invalidated_by = self.invalidated_by

        invalidation_reason: None | str | Unset
        if isinstance(self.invalidation_reason, Unset):
            invalidation_reason = UNSET
        else:
            invalidation_reason = self.invalidation_reason

        validator_score: float | None | Unset
        if isinstance(self.validator_score, Unset):
            validator_score = UNSET
        else:
            validator_score = self.validator_score

        score_components_summary: dict[str, Any] | None | Unset
        if isinstance(self.score_components_summary, Unset):
            score_components_summary = UNSET
        elif isinstance(self.score_components_summary, EvaluationRunPublicScoreComponentsSummaryType0):
            score_components_summary = self.score_components_summary.to_dict()
        else:
            score_components_summary = self.score_components_summary

        service_versions: dict[str, Any] | None | Unset
        if isinstance(self.service_versions, Unset):
            service_versions = UNSET
        elif isinstance(self.service_versions, EvaluationRunPublicServiceVersionsType0):
            service_versions = self.service_versions.to_dict()
        else:
            service_versions = self.service_versions

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "eval_run_id": eval_run_id,
                "agent_version_id": agent_version_id,
                "suite_id": suite_id,
                "validator_hotkey": validator_hotkey,
                "status": status,
                "claimed_at": claimed_at,
                "lease_expires_at": lease_expires_at,
                "is_included": is_included,
            }
        )
        if last_heartbeat_at is not UNSET:
            field_dict["last_heartbeat_at"] = last_heartbeat_at
        if completed_at is not UNSET:
            field_dict["completed_at"] = completed_at
        if invalidated_at is not UNSET:
            field_dict["invalidated_at"] = invalidated_at
        if invalidated_by is not UNSET:
            field_dict["invalidated_by"] = invalidated_by
        if invalidation_reason is not UNSET:
            field_dict["invalidation_reason"] = invalidation_reason
        if validator_score is not UNSET:
            field_dict["validator_score"] = validator_score
        if score_components_summary is not UNSET:
            field_dict["score_components_summary"] = score_components_summary
        if service_versions is not UNSET:
            field_dict["service_versions"] = service_versions

        return field_dict

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.evaluation_run_public_score_components_summary_type_0 import (
            EvaluationRunPublicScoreComponentsSummaryType0,
        )
        from ..models.evaluation_run_public_service_versions_type_0 import EvaluationRunPublicServiceVersionsType0

        d = dict(src_dict)
        eval_run_id = UUID(d.pop("eval_run_id"))

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

        suite_id = d.pop("suite_id")

        validator_hotkey = d.pop("validator_hotkey")

        status = EvaluationRunStatus(d.pop("status"))

        claimed_at = isoparse(d.pop("claimed_at"))

        lease_expires_at = isoparse(d.pop("lease_expires_at"))

        is_included = d.pop("is_included")

        def _parse_last_heartbeat_at(data: object) -> datetime.datetime | None | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, str):
                    raise TypeError()
                last_heartbeat_at_type_0 = isoparse(data)

                return last_heartbeat_at_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(datetime.datetime | None | Unset, data)

        last_heartbeat_at = _parse_last_heartbeat_at(d.pop("last_heartbeat_at", UNSET))

        def _parse_completed_at(data: object) -> datetime.datetime | None | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, str):
                    raise TypeError()
                completed_at_type_0 = isoparse(data)

                return completed_at_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(datetime.datetime | None | Unset, data)

        completed_at = _parse_completed_at(d.pop("completed_at", UNSET))

        def _parse_invalidated_at(data: object) -> datetime.datetime | None | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, str):
                    raise TypeError()
                invalidated_at_type_0 = isoparse(data)

                return invalidated_at_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(datetime.datetime | None | Unset, data)

        invalidated_at = _parse_invalidated_at(d.pop("invalidated_at", UNSET))

        def _parse_invalidated_by(data: object) -> None | str | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            return cast(None | str | Unset, data)

        invalidated_by = _parse_invalidated_by(d.pop("invalidated_by", UNSET))

        def _parse_invalidation_reason(data: object) -> None | str | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            return cast(None | str | Unset, data)

        invalidation_reason = _parse_invalidation_reason(d.pop("invalidation_reason", UNSET))

        def _parse_validator_score(data: object) -> float | None | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            return cast(float | None | Unset, data)

        validator_score = _parse_validator_score(d.pop("validator_score", UNSET))

        def _parse_score_components_summary(
            data: object,
        ) -> EvaluationRunPublicScoreComponentsSummaryType0 | None | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, dict):
                    raise TypeError()
                score_components_summary_type_0 = EvaluationRunPublicScoreComponentsSummaryType0.from_dict(data)

                return score_components_summary_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(EvaluationRunPublicScoreComponentsSummaryType0 | None | Unset, data)

        score_components_summary = _parse_score_components_summary(d.pop("score_components_summary", UNSET))

        def _parse_service_versions(data: object) -> EvaluationRunPublicServiceVersionsType0 | None | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, dict):
                    raise TypeError()
                service_versions_type_0 = EvaluationRunPublicServiceVersionsType0.from_dict(data)

                return service_versions_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(EvaluationRunPublicServiceVersionsType0 | None | Unset, data)

        service_versions = _parse_service_versions(d.pop("service_versions", UNSET))

        evaluation_run_public = cls(
            eval_run_id=eval_run_id,
            agent_version_id=agent_version_id,
            suite_id=suite_id,
            validator_hotkey=validator_hotkey,
            status=status,
            claimed_at=claimed_at,
            lease_expires_at=lease_expires_at,
            is_included=is_included,
            last_heartbeat_at=last_heartbeat_at,
            completed_at=completed_at,
            invalidated_at=invalidated_at,
            invalidated_by=invalidated_by,
            invalidation_reason=invalidation_reason,
            validator_score=validator_score,
            score_components_summary=score_components_summary,
            service_versions=service_versions,
        )

        evaluation_run_public.additional_properties = d
        return evaluation_run_public

    @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
