from __future__ import annotations

from copy import deepcopy
from typing import Any, Generic, Protocol, TypeVar

from pydantic import BaseModel

from .errors import StateValidationError

StateT = TypeVar("StateT")


class StateAdapter(Protocol[StateT]):
    def clone(self, state: StateT) -> StateT:
        ...

    def validate(self, state: StateT) -> StateT:
        ...

    def serialize(self, state: StateT) -> Any:
        ...


class DefaultStateAdapter(Generic[StateT]):
    def __init__(self, state_type: type[Any] | None = None):
        self.state_type = state_type

    def clone(self, state: StateT) -> StateT:
        if isinstance(state, BaseModel):
            return state.model_copy(deep=True)  # type: ignore[return-value]
        return deepcopy(state)

    def validate(self, state: StateT) -> StateT:
        if self.state_type is not None and not isinstance(state, self.state_type):
            raise StateValidationError(
                f"State must be an instance of {self.state_type.__name__}"
            )
        return state

    def serialize(self, state: StateT) -> Any:
        if isinstance(state, BaseModel):
            return state.model_dump(mode="json")
        return deepcopy(state)
