"""Execution environment preference for tools.

Defines intrinsic execution environment preferences that are part of
a tool's definition — not caller-supplied.  These preferences are
consulted during execution routing to determine *where* a tool should
run.

## Preference Modes

| Mode          | Behavior                                           |
|---------------|----------------------------------------------------|
| ``none``      | No preference (default); use caller-supplied env   |
| ``required``  | Must run in container; fail if unavailable         |
| ``preferred`` | Try container, fall back to host                   |
| ``specific``  | Target a named container resource                  |

Based on issue #879 — Tool-level execution environment preferences.
"""

from __future__ import annotations

from enum import StrEnum
from typing import Self

from pydantic import BaseModel, ConfigDict, Field, model_validator

__all__ = [
    "EnvironmentPreferenceMode",
    "ExecutionEnvironmentPreference",
]


class EnvironmentPreferenceMode(StrEnum):
    """Mode for tool execution environment preference.

    Controls how the tool runner interprets the tool's environment
    preference during execution routing.
    """

    NONE = "none"
    REQUIRED = "required"
    PREFERRED = "preferred"
    SPECIFIC = "specific"


class ExecutionEnvironmentPreference(BaseModel):
    """Intrinsic execution environment preference for a tool.

    Set at tool definition time (e.g. in YAML config) and consulted
    by ``ToolRunner.execute()`` before delegating to the environment
    resolver.

    When ``mode`` is ``specific``, ``target_resource`` must name the
    container resource to target (e.g. ``local/api-dev``).
    """

    model_config = ConfigDict(frozen=True, str_strip_whitespace=True)

    mode: EnvironmentPreferenceMode = Field(
        default=EnvironmentPreferenceMode.NONE,
        description="Execution environment preference mode",
    )
    target_resource: str | None = Field(
        default=None,
        description="Named container resource for 'specific' mode",
    )

    @model_validator(mode="after")
    def _validate_target(self) -> Self:
        """Enforce target_resource rules based on mode."""
        if self.mode == EnvironmentPreferenceMode.SPECIFIC and not self.target_resource:
            raise ValueError("'specific' mode requires target_resource")
        if (
            self.mode != EnvironmentPreferenceMode.SPECIFIC
            and self.target_resource is not None
        ):
            raise ValueError("target_resource only valid with 'specific' mode")
        return self
