# retoor <retoor@molodetz.nl>

from .spec import Action, Param


def arg(
    name: str, description: str, required: bool = False, kind: str = "string"
) -> Param:
    return Param(
        name=name,
        location="body",
        description=description,
        required=required,
        type=kind,
    )


SLUG = arg(
    "project_slug",
    "Project slug or uid that owns the container resources.",
    required=True,
)

CONTAINER_ACTIONS: tuple[Action, ...] = (
    Action(
        name="container_list_instances",
        method="LOCAL",
        path="",
        handler="container",
        requires_admin=True,
        read_only=True,
        summary="List a project's container instances and their status",
        params=(SLUG,),
    ),
    Action(
        name="container_create_instance",
        method="LOCAL",
        path="",
        handler="container",
        requires_admin=True,
        summary="Create and start a container instance (runs the shared ppy image with the project files mounted at /app)",
        params=(
            SLUG,
            arg("name", "Instance name.", required=True),
            arg(
                "boot_command", "Optional command to run on boot, e.g. 'python app.py'."
            ),
            arg(
                "boot_language",
                "Optional boot source language: 'none', 'python', or 'bash'. When set with boot_script, the script is materialized into /app and run on launch (takes precedence over boot_command).",
            ),
            arg(
                "boot_script",
                "Optional boot source code (the body of the python or bash script) run on launch when boot_language is python or bash.",
            ),
            arg(
                "run_as_uid",
                "Optional DevPlace user uid whose identity and API key are injected (DEVPLACE_API_KEY, DEVPLACE_USER_UID). Does NOT change the container OS user, which is always pravda (uid 1000).",
            ),
            arg(
                "start_on_boot",
                "Force this instance to running whenever the container service starts ('true' or 'false', default false).",
            ),
            arg("restart_policy", "never, always, on-failure, or unless-stopped."),
            arg("env", "Optional env vars as KEY=VALUE lines."),
            arg(
                "ports",
                "Port maps per line or comma separated. Use a bare container port (e.g. '8899') to auto-assign a unique host port above 20000, or 'host:container' to pin one.",
            ),
            arg("cpu_limit", "Optional CPU limit, e.g. 1 or 1.5."),
            arg("mem_limit", "Optional memory limit, e.g. 512m or 1g."),
            arg("autostart", "Start immediately ('true' or 'false', default true)."),
            arg(
                "ingress_slug",
                "Optional public ingress slug; the service is then reachable at /p/<slug>.",
            ),
            arg(
                "ingress_port",
                "Container port to publish at /p/<slug> (must be one of the mapped ports).",
                kind="integer",
            ),
        ),
    ),
    Action(
        name="container_instance_action",
        method="LOCAL",
        path="",
        handler="container",
        requires_admin=True,
        summary="Control an instance: start, stop, restart, pause, resume, delete, or sync",
        description="sync imports the container /app workspace back into the project files.",
        params=(
            SLUG,
            arg("instance", "Instance name, slug, or uid.", required=True),
            arg(
                "action",
                "start, stop, restart, pause, resume, delete, or sync.",
                required=True,
            ),
            arg(
                "confirm",
                "Required only for action=delete: set true ONLY after the user has explicitly "
                "confirmed destroying the instance. Leave unset otherwise; the delete is refused "
                "until you pass confirm=true.",
                kind="boolean",
            ),
        ),
    ),
    Action(
        name="container_configure_instance",
        method="LOCAL",
        path="",
        handler="container",
        requires_admin=True,
        summary="Update an instance's run-as user, boot language/script/command, restart policy, start-on-boot flag, and resource limits",
        params=(
            SLUG,
            arg("instance", "Instance name, slug, or uid.", required=True),
            arg(
                "run_as_uid",
                "DevPlace user uid whose identity and API key are injected (DEVPLACE_API_KEY, DEVPLACE_USER_UID); pass empty to clear. Does NOT change the container OS user (always pravda, uid 1000).",
            ),
            arg("boot_language", "Boot source language: 'none', 'python', or 'bash'."),
            arg("boot_script", "Boot source code body run on launch."),
            arg("boot_command", "Fallback boot command used when no boot_script is set."),
            arg("restart_policy", "never, always, on-failure, or unless-stopped."),
            arg(
                "start_on_boot",
                "Force running on container-service start ('true' or 'false').",
            ),
            arg("cpu_limit", "CPU limit, e.g. 1 or 1.5."),
            arg("mem_limit", "Memory limit, e.g. 512m or 1g."),
        ),
    ),
    Action(
        name="container_logs",
        method="LOCAL",
        path="",
        handler="container",
        requires_admin=True,
        read_only=True,
        summary="Read the recent logs of a running instance",
        params=(
            SLUG,
            arg("instance", "Instance name, slug, or uid.", required=True),
            arg("tail", "Number of log lines (default 200).", kind="integer"),
        ),
    ),
    Action(
        name="container_exec",
        method="LOCAL",
        path="",
        handler="container",
        requires_admin=True,
        summary="Run a one-shot command inside a running instance and return its output. The command runs in /app (the project workspace) by default, so never prefix it with 'cd /app'",
        params=(
            SLUG,
            arg("instance", "Instance name, slug, or uid.", required=True),
            arg(
                "command",
                "Command to run, e.g. 'git clone ... && ls'. Runs in /app already; do not prepend 'cd /app'.",
                required=True,
            ),
            arg(
                "confirm",
                "Required only when the command is destructive (rm, dd, truncate, drop, etc.): set "
                "true ONLY after the user has explicitly confirmed. Leave unset otherwise; a "
                "destructive command is refused until you pass confirm=true.",
                kind="boolean",
            ),
        ),
    ),
    Action(
        name="container_stats",
        method="LOCAL",
        path="",
        handler="container",
        requires_admin=True,
        read_only=True,
        summary="Get aggregated resource and runtime statistics for an instance",
        params=(SLUG, arg("instance", "Instance name, slug, or uid.", required=True)),
    ),
    Action(
        name="container_schedule",
        method="LOCAL",
        path="",
        handler="container",
        requires_admin=True,
        summary="Schedule a start or stop of an instance (cron, interval, or one-time)",
        params=(
            SLUG,
            arg("instance", "Instance name, slug, or uid.", required=True),
            arg("action", "start or stop.", required=True),
            arg("kind", "once, interval, or cron.", required=True),
            arg("cron", "Cron expression for kind=cron, e.g. '0 2 * * *'."),
            arg("run_at", "ISO time for kind=once, e.g. 2026-06-15T02:00:00."),
            arg("every_seconds", "Interval seconds for kind=interval.", kind="integer"),
        ),
    ),
)
