# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========

import shlex
import uuid

# Providers whose exec API has no stdin stream (Daytona, e2b) upload
# piped bytes to a per-invocation file and redirect it into the line.
STDIN_PREFIX = "/tmp/.mirage_stdin"


def stdin_path() -> str:
    """A unique in-sandbox path for one invocation's stdin bytes.

    Unique per invocation so concurrent lines on the same runtime
    never overwrite each other's payload.
    """
    return f"{STDIN_PREFIX}_{uuid.uuid4().hex}"


def stdin_redirect(line: str, path: str) -> str:
    """The line rewritten to read its stdin from an uploaded file.

    Runs the line in a subshell with stdin redirected from ``path``,
    removes the file afterward, and preserves the line's exit code.
    This is the only byte-exact stdin with a real EOF that Daytona and
    e2b allow: their exec APIs take no stdin stream, e2b's send_stdin
    cannot signal EOF, and a PTY merges streams and mangles bytes.

    Known limitations, all inherent to the file transport:
    - stdin is fully buffered and uploaded before the line starts;
      nothing is streamed, so no interactive stdin.
    - the bytes briefly touch the sandbox's /tmp, readable by other
      processes in the sandbox and left behind if the exec dies
      before the ``rm`` runs (a later line's unique path is never
      affected).
    - each stdin line costs two extra provider API calls (mkdir +
      upload).
    - the sandbox must have a POSIX sh (subshell, ``$?``, ``rm``).
    If a provider ever adds real exec stdin, drop this for that
    provider (docker already streams via ``docker exec -i``).

    Args:
        line (str): the raw shell line.
        path (str): the uploaded stdin file (from stdin_path()).
    """
    quoted = shlex.quote(path)
    return f"( {line} ) < {quoted}; _s=$?; rm -f {quoted}; exit $_s"


def sdk_install_hint(name: str) -> str:
    """The message shown when a provider SDK extra is missing.

    Args:
        name (str): the runtime name, which is also its pip extra
            (daytona, e2b).
    """
    return (f"the {name} runtime needs the {name} SDK; install with: "
            f"pip install mirage-ai[{name}]")
