# tests/test_config.py
import yaml
from agentsh_secure_sandbox.core.types import (
    SecureConfig, ThreatFeed, ThreatFeedsConfig,
    ServerConfig, PtraceConfig, PtraceTraceConfig,
    PtracePerformanceConfig, FuseConfig, GrpcConfig, LoggingConfig,
    SessionsConfig, AuditConfig, SandboxLimitsConfig, CgroupsConfig,
    UnixSocketsConfig, NetworkInterceptConfig, DlpConfig,
    MetricsConfig, HealthConfig, ApprovalsConfig, PackageChecksConfig,
    ProviderConfig, DevelopmentConfig, PolicySigningConfig,
    SeccompDetailsConfig, FileMonitorConfig,
)
from agentsh_secure_sandbox.core.config import generate_server_config


def test_default_config():
    cfg = SecureConfig()
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["server"]["http"]["addr"] == "127.0.0.1:18080"
    assert result["auth"]["type"] == "none"
    assert result["policies"]["system_dir"] == "/etc/agentsh/system"
    assert result["policies"]["dir"] == "/etc/agentsh"
    assert result["policies"]["default"] == "policy"
    assert result["workspace"] == "/workspace"
    assert result["sandbox"]["enabled"] is True


def test_custom_workspace():
    cfg = SecureConfig(workspace="/home/agent")
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["workspace"] == "/home/agent"


def test_custom_policy_name():
    cfg = SecureConfig(policy_name="my-policy")
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["policies"]["default"] == "my-policy"


def test_default_threat_feeds():
    cfg = SecureConfig()
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["threat_feeds"]["enabled"] is True
    assert len(result["threat_feeds"]["feeds"]) == 2


def test_threat_feeds_disabled():
    cfg = SecureConfig(threat_feeds=False)
    result = yaml.safe_load(generate_server_config(cfg))
    assert "threat_feeds" not in result


def test_custom_threat_feeds():
    cfg = SecureConfig(
        threat_feeds=ThreatFeedsConfig(
            feeds=[ThreatFeed(name="custom", url="https://example.com/list", format="domain-list")],
            action="audit",
        )
    )
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["threat_feeds"]["action"] == "audit"
    assert result["threat_feeds"]["feeds"][0]["name"] == "custom"


def test_real_paths_included():
    cfg = SecureConfig(real_paths=True)
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sandbox"]["real_paths"] is True


def test_watchtower():
    cfg = SecureConfig(watchtower="https://watchtower.example.com")
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["watchtower"]["url"] == "https://watchtower.example.com"


def test_config_with_grpc():
    cfg = SecureConfig(server_config=ServerConfig(grpc=GrpcConfig(addr="127.0.0.1:9090")))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["server"]["grpc"]["enabled"] is True
    assert result["server"]["grpc"]["addr"] == "127.0.0.1:9090"


def test_config_with_ptrace():
    cfg = SecureConfig(server_config=ServerConfig(ptrace=PtraceConfig(
        enabled=True, attach_mode="children",
        trace=PtraceTraceConfig(execve=True, file=False, network=True, signal=True),
        performance=PtracePerformanceConfig(seccomp_prefilter=False, max_tracees=500, max_hold_ms=5000),
        on_attach_failure="fail_open",
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    ptrace = result["sandbox"]["ptrace"]
    assert ptrace["enabled"] is True
    assert ptrace["attach_mode"] == "children"
    assert ptrace["trace"]["execve"] is True
    assert ptrace["trace"]["file"] is False
    assert ptrace["performance"]["seccomp_prefilter"] is False
    assert ptrace["on_attach_failure"] == "fail_open"


def test_config_with_fuse_deferred():
    cfg = SecureConfig(server_config=ServerConfig(fuse=FuseConfig(
        deferred=True, deferred_marker_file="/tmp/.marker",
        deferred_enable_command=["/bin/chmod", "666", "/dev/fuse"],
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    fuse = result["sandbox"]["fuse"]
    assert fuse["deferred"] is True
    assert fuse["deferred_marker_file"] == "/tmp/.marker"


def test_config_with_cgroups_disabled():
    cfg = SecureConfig(server_config=ServerConfig(cgroups=CgroupsConfig(enabled=False)))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sandbox"]["cgroups"]["enabled"] is False


def test_config_with_unix_sockets():
    cfg = SecureConfig(server_config=ServerConfig(unix_sockets=UnixSocketsConfig(enabled=False)))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sandbox"]["unix_sockets"]["enabled"] is False


def test_config_with_dlp():
    cfg = SecureConfig(server_config=ServerConfig(dlp=DlpConfig(
        mode="redact", patterns={"api_keys": True, "credit_card": True},
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["dlp"]["mode"] == "redact"
    assert result["dlp"]["patterns"]["api_keys"] is True


def test_config_with_sessions():
    cfg = SecureConfig(server_config=ServerConfig(sessions=SessionsConfig(
        default_timeout="1h", idle_timeout="15m",
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sessions"]["default_timeout"] == "1h"


def test_config_with_audit():
    cfg = SecureConfig(server_config=ServerConfig(audit=AuditConfig(
        enabled=True, sqlite_path="/var/lib/agentsh/events.db",
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["audit"]["enabled"] is True


def test_config_with_sandbox_limits():
    cfg = SecureConfig(server_config=ServerConfig(sandbox_limits=SandboxLimitsConfig(
        max_memory_mb=4096, max_cpu_percent=100,
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sandbox"]["limits"]["max_memory_mb"] == 4096


def test_config_with_package_checks():
    cfg = SecureConfig(package_checks=PackageChecksConfig(
        scope="new_packages_only",
        providers={"osv": ProviderConfig(enabled=True, priority=1)},
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["package_checks"]["enabled"] is True
    assert result["package_checks"]["scope"] == "new_packages_only"


def test_config_with_env_inject():
    cfg = SecureConfig(server_config=ServerConfig(
        env_inject={"BASH_ENV": "/usr/lib/agentsh/bash_startup.sh"},
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sandbox"]["env_inject"]["BASH_ENV"] == "/usr/lib/agentsh/bash_startup.sh"


def test_config_sessions_base_dir_default():
    cfg = SecureConfig()
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sessions"]["base_dir"] == "/var/lib/agentsh/sessions"


def test_config_with_network_intercept():
    cfg = SecureConfig(server_config=ServerConfig(
        network_intercept=NetworkInterceptConfig(intercept_mode="all", proxy_listen_addr="127.0.0.1:0"),
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sandbox"]["network"]["intercept_mode"] == "all"


def test_config_with_logging():
    cfg = SecureConfig(server_config=ServerConfig(
        logging=LoggingConfig(level="info", format="text", output="stderr"),
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["logging"]["level"] == "info"


def test_config_with_health():
    cfg = SecureConfig(server_config=ServerConfig(
        health=HealthConfig(path="/health", readiness_path="/ready"),
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["health"]["path"] == "/health"
    assert result["health"]["readiness_path"] == "/ready"


def test_config_with_metrics():
    cfg = SecureConfig(server_config=ServerConfig(
        metrics=MetricsConfig(enabled=True, path="/metrics"),
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["metrics"]["enabled"] is True


def test_config_with_approvals():
    cfg = SecureConfig(server_config=ServerConfig(
        approvals=ApprovalsConfig(enabled=False),
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["approvals"]["enabled"] is False


def test_config_with_development():
    cfg = SecureConfig(server_config=ServerConfig(
        development=DevelopmentConfig(disable_auth=True, verbose_errors=True),
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["development"]["disable_auth"] is True


def test_config_allow_degraded_override():
    cfg = SecureConfig(server_config=ServerConfig(allow_degraded=False))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sandbox"]["allow_degraded"] is False


# ─── v0.16.9 config tests ─────────────────────────────


def test_default_unix_sockets_disabled():
    """unix_sockets is disabled by default in v0.16.9+."""
    cfg = SecureConfig()
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["sandbox"]["unix_sockets"]["enabled"] is False


def test_audit_storage_nesting():
    """sqlite_path nests under storage in v0.16.9+."""
    cfg = SecureConfig(server_config=ServerConfig(audit=AuditConfig(
        enabled=True,
        sqlite_path="/var/lib/agentsh/events.db",
        batch_size=100,
        flush_interval="5s",
        channel_size=1000,
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["audit"]["enabled"] is True
    assert result["audit"]["storage"]["sqlite_path"] == "/var/lib/agentsh/events.db"
    assert result["audit"]["storage"]["batch_size"] == 100
    assert result["audit"]["storage"]["flush_interval"] == "5s"
    assert result["audit"]["storage"]["channel_size"] == 1000


def test_policy_signing():
    cfg = SecureConfig(server_config=ServerConfig(
        policy_signing=PolicySigningConfig(trust_store="/etc/agentsh/keys", mode="enforce"),
    ))
    result = yaml.safe_load(generate_server_config(cfg))
    assert result["policies"]["signing"]["trust_store"] == "/etc/agentsh/keys"
    assert result["policies"]["signing"]["mode"] == "enforce"


def test_ptrace_new_performance_fields():
    cfg = SecureConfig(server_config=ServerConfig(ptrace=PtraceConfig(
        enabled=True,
        performance=PtracePerformanceConfig(
            seccomp_prefilter=False,
            max_tracees=500,
            static_allow_file=True,
            static_allow_network=True,
            arg_level_filter=True,
        ),
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    perf = result["sandbox"]["ptrace"]["performance"]
    assert perf["static_allow_file"] is True
    assert perf["static_allow_network"] is True
    assert perf["arg_level_filter"] is True


def test_file_monitor_new_fields():
    cfg = SecureConfig(server_config=ServerConfig(seccomp_details=SeccompDetailsConfig(
        file_monitor=FileMonitorConfig(
            enabled=True,
            intercept_metadata=True,
            openat_emulation=True,
            block_io_uring=True,
        ),
    )))
    result = yaml.safe_load(generate_server_config(cfg))
    fm = result["sandbox"]["seccomp"]["file_monitor"]
    assert fm["enabled"] is True
    assert fm["intercept_metadata"] is True
    assert fm["openat_emulation"] is True
    assert fm["block_io_uring"] is True
