from __future__ import annotations

from dataclasses import dataclass
from typing import Generic, Protocol, TypeVar


StateT = TypeVar("StateT")
CandidateT = TypeVar("CandidateT")
CritiqueT = TypeVar("CritiqueT")
CategoryT = TypeVar("CategoryT")


@dataclass(frozen=True)
class PolicyDecision:
    accepted: bool
    label: str = ""


class Generator(Protocol[StateT, CandidateT]):
    def generate(self, state: StateT) -> CandidateT:
        ...


class Critic(Protocol[StateT, CandidateT, CritiqueT]):
    def critique(self, state: StateT, candidate: CandidateT) -> CritiqueT:
        ...


class Categorizer(Protocol[StateT, CandidateT, CategoryT]):
    def categorize(self, state: StateT, candidate: CandidateT) -> CategoryT:
        ...


class AcceptancePolicy(Protocol[StateT, CandidateT, CritiqueT, CategoryT]):
    def decide(
        self,
        state: StateT,
        candidate: CandidateT,
        critique: CritiqueT,
        category: CategoryT,
    ) -> PolicyDecision:
        ...


class StateTransition(Protocol[StateT, CandidateT, CritiqueT, CategoryT]):
    def advance(
        self,
        state: StateT,
        candidate: CandidateT,
        critique: CritiqueT,
        category: CategoryT,
        decision: PolicyDecision,
    ) -> StateT:
        ...
