# src/agentsh_secure_sandbox/policies/presets.py
# mypy: disable-error-code="list-item"
"""Built-in policy presets for common use cases.

See spec Section 7.3 for full preset definitions.
"""

from __future__ import annotations

from .merge import merge
from .schema import PolicyDefinition


def agent_default(
    extensions: PolicyDefinition | None = None,
) -> PolicyDefinition:
    """Comprehensive policy for AI coding agents.

    This is the DEFAULT policy used when no policy is specified.
    """
    base = PolicyDefinition(
        file=[
            # Denies first — first-match-wins means these block before broad allows
            {"deny": ["/workspace/.git/config", "/workspace/.netrc"]},
            {"deny": ["**/.env", "**/.env.*", "**/credentials*", "**/*.pem", "**/*.key"]},
            {"deny": ["~/.ssh/**", "/proc/*/environ"]},
            {"deny": ["~/.aws/**", "~/.gcp/**", "~/.azure/**", "~/.config/gcloud/**"]},
            {"deny": ["~/.bashrc", "~/.zshrc", "~/.profile", "~/.bash_profile"]},
            {"deny": ["~/.gitconfig", "~/.netrc", "~/.curlrc", "~/.wgetrc"]},
            {"deny": "~/.local/bin/**"},
            {
                "deny": ["**/.cursorrules", "**/CLAUDE.md", "**/copilot-instructions.md"],
                "ops": ["write", "create", "delete"],
            },
            # Allows after denies
            {"allow": "/workspace/**", "ops": ["read", "write", "create", "delete"]},
        ],
        network=[
            {
                "allow": [
                    "registry.npmjs.org",
                    "registry.yarnpkg.com",
                    "pypi.org",
                    "files.pythonhosted.org",
                    "crates.io",
                    "static.crates.io",
                    "index.crates.io",
                    "proxy.golang.org",
                    "sum.golang.org",
                    "github.com",
                    "raw.githubusercontent.com",
                ],
                "ports": [443],
            },
            {"deny": "*"},
        ],
        commands=[
            # Denies first
            {"deny": ["env", "printenv", "sudo", "su", "doas"]},
            {"deny": ["shutdown", "reboot", "halt", "poweroff"]},
            {"deny": ["nc", "ncat", "netcat", "socat", "telnet"]},
            {"deny": ["git push --force", "git reset --hard"]},
            # Allows after denies
            {
                "allow": [
                    "bash",
                    "sh",
                    "echo",
                    "cat",
                    "head",
                    "tail",
                    "grep",
                    "find",
                    "ls",
                    "wc",
                    "sort",
                    "uniq",
                    "diff",
                    "pwd",
                    "date",
                    "which",
                    "whoami",
                    "id",
                    "uname",
                    "printf",
                    "test",
                    "true",
                    "false",
                    "mkdir",
                    "cp",
                    "mv",
                    "rm",
                    "touch",
                    "chmod",
                    "tr",
                    "cut",
                    "sed",
                    "awk",
                    "tee",
                    "xargs",
                    "basename",
                    "dirname",
                    "realpath",
                    "base64",
                    "md5sum",
                    "sha256sum",
                    "tar",
                    "gzip",
                    "gunzip",
                ],
            },
            {
                "allow": [
                    "git",
                    "node",
                    "npm",
                    "npx",
                    "yarn",
                    "pnpm",
                    "bun",
                    "python",
                    "python3",
                    "pip",
                    "pip3",
                    "cargo",
                    "rustc",
                    "go",
                    "make",
                    "cmake",
                ],
            },
            # Redirects at end
            {
                "redirect": ["curl", "wget"],
                "to": {"cmd": "agentsh-fetch", "args": ["--audit"]},
            },
        ],
    )
    return merge(base, extensions) if extensions else base


def dev_safe(
    extensions: PolicyDefinition | None = None,
) -> PolicyDefinition:
    """Permissive defaults for local development.

    Allows broader network access and file operations. Still denies
    credential access and privilege escalation.
    """
    base = PolicyDefinition(
        file=[
            # Denies first
            {"deny": ["**/.env", "**/.env.*", "**/credentials*", "**/*.pem", "**/*.key"]},
            {"deny": ["~/.ssh/**", "/proc/*/environ"]},
            {"deny": ["~/.aws/**", "~/.gcp/**", "~/.azure/**", "~/.config/gcloud/**"]},
            # Allows after denies
            {"allow": "/workspace/**"},
        ],
        network=[
            {"allow": "*", "ports": [80, 443]},
            {"deny": ["169.254.169.254", "metadata.google.internal"]},
        ],
        commands=[
            {"deny": ["sudo", "su", "doas"]},
            {"deny": ["shutdown", "reboot", "halt", "poweroff"]},
            {"allow": ["bash", "sh"]},
            {
                "redirect": ["curl", "wget"],
                "to": {"cmd": "agentsh-fetch", "args": ["--audit"]},
            },
        ],
    )
    return merge(base, extensions) if extensions else base


def ci_strict(
    extensions: PolicyDefinition | None = None,
) -> PolicyDefinition:
    """Locked down for CI/CD runners.

    Read-only workspace except build output dirs. Network limited to
    package registries. No interactive commands.
    """
    base = PolicyDefinition(
        file=[
            # Denies first
            {"deny": ["**/.env", "**/.env.*", "**/credentials*", "**/*.pem", "**/*.key"]},
            {"deny": ["~/.ssh/**", "~/.aws/**", "~/.gcp/**", "~/.azure/**"]},
            {"deny": ["/proc/*/environ"]},
            # Allows after denies
            {"allow": "/workspace/**", "ops": ["read"]},
            {
                "allow": [
                    "/workspace/build/**",
                    "/workspace/dist/**",
                    "/workspace/target/**",
                ],
                "ops": ["read", "write", "create", "delete"],
            },
        ],
        network=[
            {
                "allow": [
                    "registry.npmjs.org",
                    "registry.yarnpkg.com",
                    "pypi.org",
                    "files.pythonhosted.org",
                    "crates.io",
                    "static.crates.io",
                    "index.crates.io",
                    "proxy.golang.org",
                    "sum.golang.org",
                    "github.com",
                    "raw.githubusercontent.com",
                ],
                "ports": [443],
            },
            {"deny": "*"},
        ],
        commands=[
            # Denies first
            {"deny": ["env", "printenv", "sudo", "su", "doas"]},
            {"deny": ["shutdown", "reboot", "halt", "poweroff"]},
            {"deny": ["nc", "ncat", "netcat", "socat", "telnet"]},
            {"deny": ["git push --force", "git reset --hard"]},
            # Allows after denies
            {
                "allow": [
                    "bash",
                    "sh",
                    "echo",
                    "cat",
                    "head",
                    "tail",
                    "grep",
                    "find",
                    "ls",
                    "wc",
                    "sort",
                    "uniq",
                    "diff",
                    "pwd",
                    "date",
                    "which",
                    "mkdir",
                    "cp",
                    "mv",
                    "rm",
                    "touch",
                    "chmod",
                    "base64",
                    "sha256sum",
                    "tar",
                    "gzip",
                    "gunzip",
                ],
            },
            {
                "allow": [
                    "git",
                    "node",
                    "npm",
                    "npx",
                    "yarn",
                    "pnpm",
                    "python",
                    "python3",
                    "pip",
                    "pip3",
                    "cargo",
                    "rustc",
                    "go",
                    "make",
                    "cmake",
                ],
            },
            # Redirects at end
            {
                "redirect": ["curl", "wget"],
                "to": {"cmd": "agentsh-fetch", "args": ["--audit"]},
            },
        ],
    )
    return merge(base, extensions) if extensions else base


def agent_sandbox(
    extensions: PolicyDefinition | None = None,
) -> PolicyDefinition:
    """Maximum restriction for untrusted code.

    Read-only workspace, no network, no dangerous commands.
    """
    base = PolicyDefinition(
        file=[
            # Denies first
            {"deny": ["**/.env", "**/.env.*", "**/credentials*", "**/*.pem", "**/*.key"]},
            {"deny": ["~/.ssh/**", "~/.aws/**", "~/.gcp/**", "~/.azure/**"]},
            {"deny": ["/proc/*/environ"]},
            # Allows after denies
            {"allow": "/workspace/**", "ops": ["read"]},
            {"allow": "/tmp/**"},
        ],
        network=[
            {"deny": "*"},
        ],
        commands=[
            # Denies first
            {"deny": ["bash", "sh"]},
            {"deny": ["env", "printenv", "sudo", "su", "doas"]},
            {"deny": ["shutdown", "reboot", "halt", "poweroff"]},
            {"deny": ["nc", "ncat", "netcat", "socat", "telnet"]},
            {"deny": ["curl", "wget", "git", "pip", "npm"]},
            # Allows after denies
            {
                "allow": [
                    "echo",
                    "cat",
                    "head",
                    "tail",
                    "grep",
                    "find",
                    "ls",
                    "wc",
                    "sort",
                    "uniq",
                    "diff",
                    "pwd",
                    "date",
                    "test",
                    "true",
                    "false",
                    "printf",
                    "basename",
                    "dirname",
                ],
            },
        ],
    )
    return merge(base, extensions) if extensions else base
