# This file was auto-generated by Fern from our API Definition.

import datetime as dt
import typing

from ....core.datetime_utils import serialize_datetime
from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1


class Trace(pydantic_v1.BaseModel):
    id: str = pydantic_v1.Field()
    """
    The unique identifier of a trace
    """

    timestamp: dt.datetime = pydantic_v1.Field()
    """
    The timestamp when the trace was created
    """

    _name: typing.Optional[str] = pydantic_v1.Field(default=None, alias="name")
    """
    The name of the trace
    """

    input: typing.Optional[typing.Any] = pydantic_v1.Field(default=None)
    """
    The input data of the trace. Can be any JSON.
    """

    output: typing.Optional[typing.Any] = pydantic_v1.Field(default=None)
    """
    The output data of the trace. Can be any JSON.
    """

    session_id: typing.Optional[str] = pydantic_v1.Field(
        alias="sessionId", default=None
    )
    """
    The session identifier associated with the trace
    """

    release: typing.Optional[str] = pydantic_v1.Field(default=None)
    """
    The release version of the application when the trace was created
    """

    version: typing.Optional[str] = pydantic_v1.Field(default=None)
    """
    The version of the trace
    """

    user_id: typing.Optional[str] = pydantic_v1.Field(alias="userId", default=None)
    """
    The user identifier associated with the trace
    """

    metadata: typing.Optional[typing.Any] = pydantic_v1.Field(default=None)
    """
    The metadata associated with the trace. Can be any JSON.
    """

    tags: typing.Optional[typing.List[str]] = pydantic_v1.Field(default=None)
    """
    The tags associated with the trace. Can be an array of strings or null.
    """

    public: typing.Optional[bool] = pydantic_v1.Field(default=None)
    """
    Public traces are accessible via url without login
    """

    environment: typing.Optional[str] = pydantic_v1.Field(default=None)
    """
    The environment from which this trace originated. Can be any lowercase alphanumeric string with hyphens and underscores that does not start with 'langfuse'.
    """

    @property
    def name(self) -> typing.Optional[str]:
        """
        Get the name of the trace. Returns client_provided_name from metadata if available,
        otherwise returns the internal name field.
        """
        if (
            self.metadata
            and isinstance(self.metadata, dict)
            and "client_provided_name" in self.metadata
        ):
            return self.metadata["client_provided_name"]
        return self.__dict__.get("name")

    @pydantic_v1.root_validator(pre=True)
    @classmethod
    def _sync_name_to_metadata(
        cls, values: typing.Dict[str, typing.Any]
    ) -> typing.Dict[str, typing.Any]:
        """
        Root validator to ensure that when name is provided, it's also stored as
        client_provided_name in the metadata for backwards compatibility.
        Only sets client_provided_name if it doesn't already exist in metadata.
        """
        name = values.get("name")
        if name is not None:
            # Initialize metadata if it doesn't exist
            if "metadata" not in values or values["metadata"] is None:
                values["metadata"] = {}

            # Ensure metadata is a dict and only set client_provided_name if it doesn't exist
            if isinstance(values["metadata"], dict):
                if "client_provided_name" not in values["metadata"]:
                    values["metadata"]["client_provided_name"] = name

        return values

    def json(self, **kwargs: typing.Any) -> str:
        kwargs_with_defaults: typing.Any = {
            "by_alias": True,
            "exclude_unset": True,
            **kwargs,
        }
        return super().json(**kwargs_with_defaults)

    def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
        kwargs_with_defaults_exclude_unset: typing.Any = {
            "by_alias": True,
            "exclude_unset": True,
            **kwargs,
        }
        kwargs_with_defaults_exclude_none: typing.Any = {
            "by_alias": True,
            "exclude_none": True,
            **kwargs,
        }

        return deep_union_pydantic_dicts(
            super().dict(**kwargs_with_defaults_exclude_unset),
            super().dict(**kwargs_with_defaults_exclude_none),
        )

    class Config:
        frozen = True
        smart_union = True
        allow_population_by_field_name = True
        populate_by_name = True
        extra = pydantic_v1.Extra.allow
        json_encoders = {dt.datetime: serialize_datetime}
