"""
FilesManager - 通过 envd 兼容层（port 49983）读写 sandbox 内文件

envd REST API：
  GET  /files?path=<url-encoded-path>  → 返回文件内容
  POST /files?path=<url-encoded-path>  → multipart/form-data 上传文件
"""

from typing import TYPE_CHECKING, Iterator, Literal, Union, overload
from urllib.parse import quote as url_quote

import httpx

if TYPE_CHECKING:
    from .sandbox import Sandbox


class FilesManager:
    """在 sandbox 中读写文件（通过 envd 兼容层）"""

    def __init__(self, sandbox: "Sandbox"):
        self._sandbox = sandbox

    @overload
    def read(self, path: str, format: Literal["bytes"]) -> bytearray: ...

    @overload
    def read(self, path: str, format: Literal["text"]) -> str: ...

    @overload
    def read(self, path: str, format: Literal["stream"]) -> Iterator[bytes]: ...

    def read(
        self,
        path: str,
        format: Literal["bytes", "text", "stream"] = "bytes",
    ):
        """
        从 sandbox 读取文件。

        :param path: sandbox 内文件的绝对路径
        :param format: 返回格式，'bytes'（bytearray）| 'text'（str）| 'stream'（生成器）
        :return: 文件内容
        """
        base = self._sandbox._get_envd_base_url()
        headers = self._sandbox._get_envd_headers()
        url = f"{base}/files?path={url_quote(path)}"

        if format == "stream":
            def _stream_gen():
                with httpx.stream("GET", url, headers=headers, timeout=60) as resp:
                    resp.raise_for_status()
                    for chunk in resp.iter_bytes():
                        yield chunk
            return _stream_gen()

        resp = httpx.get(url, headers=headers, timeout=60)
        resp.raise_for_status()

        if format == "text":
            return resp.text
        # default: bytes → bytearray
        return bytearray(resp.content)

    def write(
        self,
        path: str,
        content: Union[str, bytes, bytearray],
        mode: str = "644",
        create_dir: bool = True,
    ):
        """
        将内容写入 sandbox 文件。

        :param path: sandbox 内文件的绝对路径
        :param content: 文件内容（字符串或字节）
        :param mode: 文件权限（如 '644'）
        :param create_dir: 若目录不存在，是否自动创建（通过 mkdir -p）
        """
        from .commands import CommandsManager

        if create_dir:
            import os as _os
            dir_path = _os.path.dirname(path)
            if dir_path and dir_path != "/":
                try:
                    cmds = CommandsManager(self._sandbox)
                    cmds.run(f"mkdir -p {dir_path}", timeout=10)
                except Exception:
                    pass

        base = self._sandbox._get_envd_base_url()
        headers = self._sandbox._get_envd_headers()
        url = f"{base}/files?path={url_quote(path)}"

        if isinstance(content, str):
            content_bytes = content.encode("utf-8")
        else:
            content_bytes = bytes(content)

        resp = httpx.post(
            url,
            files={"file": (path.split("/")[-1], content_bytes)},
            headers=headers,
            timeout=60,
        )
        resp.raise_for_status()

    def remove(self, path: str, force: bool = False):
        """
        删除 sandbox 内的文件。

        :param path: sandbox 内文件的绝对路径
        :param force: 是否强制删除（-f 参数）
        """
        from .commands import CommandsManager
        flag = "-f" if force else ""
        cmds = CommandsManager(self._sandbox)
        cmds.run(f"rm {flag} {path}", timeout=15)
