# adapters/cloudflare.py

from __future__ import annotations
import base64
from typing import Any
from ..core.types import ExecResult, ExecOpts
from ..core.shell import shell_escape, fire_and_forget


def cloudflare(sandbox: Any) -> _CloudflareAdapter:
    return _CloudflareAdapter(sandbox)


class _CloudflareAdapter:
    def __init__(self, sandbox: Any) -> None:
        self._sb = sandbox

    async def exec(
        self,
        cmd: str,
        args: list[str] | None = None,
        opts: ExecOpts | None = None,
    ) -> ExecResult:
        opts = opts or ExecOpts()
        command = shell_escape(cmd, args)
        # Cloudflare runs as root — sudo flag is silently ignored.

        if opts.detached:
            fire_and_forget(self._sb.exec(f"nohup {command} > /dev/null 2>&1 &", cwd=opts.cwd))
            return ExecResult(stdout="", stderr="", exit_code=0)

        result = await self._sb.exec(command, cwd=opts.cwd)
        return ExecResult(
            stdout=result.stdout or "",
            stderr=result.stderr or "",
            exit_code=result.exit_code,
        )

    async def write_file(self, path: str, content: str | bytes, *, sudo: bool = False) -> None:
        data = content if isinstance(content, bytes) else content.encode()
        b64 = base64.b64encode(data).decode("ascii")
        # Note: base64 shell argument limits this to files ~96KB (128KB ARG_MAX).
        # For larger files, use chunked writes via multiple exec calls.
        cmd = shell_escape("sh", ["-c", 'printf "%s" "$1" | base64 -d > "$2"', "_", b64, path])
        result = await self._sb.exec(cmd)
        if (result.exit_code or 0) != 0:
            raise RuntimeError(f"writeFile failed (exit {result.exit_code}): {result.stderr or ''}")

    async def read_file(self, path: str) -> str:
        cmd = shell_escape("cat", [path])
        result = await self._sb.exec(cmd)
        if (result.exit_code or 0) != 0:
            raise RuntimeError(f"readFile failed (exit {result.exit_code}): {result.stderr or ''}")
        return result.stdout or ""

    async def stop(self) -> None:
        pass  # Cloudflare manages container lifecycle

    async def file_exists(self, path: str) -> bool:
        result = await self.exec("test", ["-f", path])
        return result.exit_code == 0
