import pytest
from pydantic import ValidationError

import dify_agent.layers.shell as shell_exports
from dify_agent.layers.shell import (
    DIFY_SHELL_LAYER_TYPE_ID,
    DifyShellCliToolConfig,
    DifyShellEnvVarConfig,
    DifyShellLayerConfig,
    DifyShellSandboxConfig,
    DifyShellSecretRefConfig,
)


def test_shell_package_exports_client_safe_config_symbols_only() -> None:
    assert shell_exports.__all__ == [
        "DIFY_SHELL_LAYER_TYPE_ID",
        "DifyShellCliToolConfig",
        "DifyShellEnvVarConfig",
        "DifyShellLayerConfig",
        "DifyShellSandboxConfig",
        "DifyShellSecretRefConfig",
    ]
    assert DIFY_SHELL_LAYER_TYPE_ID == "dify.shell"
    assert not hasattr(shell_exports, "DifyShellLayer")


def test_shell_layer_config_defaults_and_forbids_unknown_fields() -> None:
    config = DifyShellLayerConfig()

    assert config.model_dump() == {
        "cli_tools": [],
        "env": [],
        "secret_refs": [],
        "sandbox": None,
    }

    with pytest.raises(ValidationError):
        _ = DifyShellLayerConfig.model_validate({"entrypoint": "http://shellctl"})


def test_shell_layer_config_accepts_agent_soul_shell_settings() -> None:
    config = DifyShellLayerConfig(
        cli_tools=[
            DifyShellCliToolConfig(
                name="ripgrep",
                install_commands=["  apt-get update  ", "", "apt-get install -y ripgrep"],
                env=[DifyShellEnvVarConfig(name="RG_CONFIG_PATH", value="/workspace/.ripgreprc")],
                secret_refs=[DifyShellSecretRefConfig(name="GITHUB_TOKEN", ref="credential-2")],
            )
        ],
        env=[DifyShellEnvVarConfig(name="PROJECT_NAME", value="demo")],
        secret_refs=[DifyShellSecretRefConfig(name="OPENAI_API_KEY", ref="credential-1")],
        sandbox=DifyShellSandboxConfig(provider="independent", config={"cpu": 2}),
    )

    assert config.cli_tools[0].install_commands == ["apt-get update", "apt-get install -y ripgrep"]
    assert config.cli_tools[0].env[0].name == "RG_CONFIG_PATH"
    assert config.cli_tools[0].secret_refs[0].ref == "credential-2"
    assert config.env[0].name == "PROJECT_NAME"
    assert config.secret_refs[0].ref == "credential-1"
    assert config.sandbox is not None
    assert config.sandbox.config == {"cpu": 2}


def test_shell_layer_config_rejects_invalid_env_names() -> None:
    with pytest.raises(ValidationError):
        _ = DifyShellEnvVarConfig(name="1_BAD", value="x")

    with pytest.raises(ValidationError):
        _ = DifyShellSecretRefConfig(name="BAD-NAME", ref="secret")
