"""
ssh_docker_prune 工具測試
==========================
ADR-068 飛輪 — disk full SOP（2026-05-02 ogt + Claude Sonnet 4.6）

測試項目：
- ssh_docker_prune 在 GROUP_B_TOOLS 白名單內
- list_tools() 回傳含 ssh_docker_prune 且 schema 正確
- _build_command() 產生包含 75% 磁碟守衛 + image/volume/builder prune 鏈
- _build_command() 不會引入 FORBIDDEN_PATTERNS（rm -rf, $( ), backtick 等）
"""

from __future__ import annotations

import asyncio

from src.plugins.mcp.providers.ssh_provider import (
    DOCKER_PRUNE_DISK_GATE_PCT,
    GROUP_B_TOOLS,
    SSHProvider,
)


class TestDockerPruneToolRegistration:
    """白名單與 list_tools() 註冊"""

    def test_in_group_b(self):
        assert "ssh_docker_prune" in GROUP_B_TOOLS

    def test_disk_gate_constant(self):
        # 守衛閾值合理（不會太低誤觸，不會太高永遠不跑）
        assert 50 <= DOCKER_PRUNE_DISK_GATE_PCT <= 90

    def test_listed_with_schema(self):
        provider = SSHProvider()
        tools = asyncio.run(provider.list_tools())
        prune = next((t for t in tools if t.name == "ssh_docker_prune"), None)
        assert prune is not None, "ssh_docker_prune not registered in list_tools()"
        assert prune.server_name == provider.name
        assert "host" in prune.input_schema["required"]
        assert "trust_score" in prune.input_schema["required"]


class TestDockerPruneCommand:
    """命令字串建構"""

    def _cmd(self) -> str:
        provider = SSHProvider()
        return provider._build_command("ssh_docker_prune", {"host": "192.168.0.110"})

    def test_includes_disk_gate(self):
        cmd = self._cmd()
        # 應該先檢查磁碟使用率，低於閾值就 skip
        assert "df --output=pcent" in cmd
        assert f"{DOCKER_PRUNE_DISK_GATE_PCT}" in cmd
        assert "skip" in cmd

    def test_includes_full_prune_chain(self):
        cmd = self._cmd()
        assert "docker image prune -a -f" in cmd
        assert "docker volume prune -f" in cmd
        assert "docker builder prune -a -f" in cmd

    def test_reports_disk_before_and_after(self):
        cmd = self._cmd()
        assert "DISK BEFORE" in cmd
        assert "DISK AFTER" in cmd

    def test_no_destructive_outside_docker(self):
        """命令只該動 docker 子系統，不該有 rm -rf / 寫 /etc / 改 sudoers"""
        cmd = self._cmd()
        assert "rm -rf" not in cmd
        assert "/etc/" not in cmd
        assert "sudoers" not in cmd
        assert "authorized_keys" not in cmd

    def test_only_uses_safe_params(self):
        """ssh_docker_prune 不接受 user-supplied 字串 params（只有 host/trust_score）"""
        provider = SSHProvider()
        tools = asyncio.run(provider.list_tools())
        prune = next(t for t in tools if t.name == "ssh_docker_prune")
        # schema 只有 host (string, whitelist-checked) + trust_score (number)
        assert set(prune.input_schema["properties"].keys()) == {"host", "trust_score"}
