from __future__ import annotations

import re
from pathlib import Path
from typing import Any

from aicd.tools.fs_tool import FSTool


class TextTool:
    def __init__(self, fs: FSTool) -> None:
        self._fs = fs

    def regex_replace(
        self, path: str, pattern: str, replacement: str, count: int = 0
    ) -> dict[str, Any]:
        r = self._fs.read_file(path)
        if not r.get("ok"):
            return r
        if r.get("truncated") or r.get("text") is None:
            return {"ok": False, "error": "file not utf-8 text or too large"}
        text = r["text"]
        assert isinstance(text, str)
        try:
            rx = re.compile(pattern)
        except re.error as e:
            return {"ok": False, "error": f"invalid regex: {e}"}
        new_text, n = rx.subn(replacement, text, count=count or 0)
        w = self._fs.write_file(path, new_text)
        if not w.get("ok"):
            return w
        return {"ok": True, "path": path, "replacements": n}

    def patch_bytes(
        self, path: str, offset: int, data_hex: str
    ) -> dict[str, Any]:
        try:
            patch = bytes.fromhex(data_hex.replace(" ", ""))
        except ValueError as e:
            return {"ok": False, "error": str(e)}
        r = self._fs.read_bytes_full(path)
        if not r.get("ok"):
            return r
        raw = bytearray(r["data"])
        assert isinstance(raw, bytearray)
        end = offset + len(patch)
        if offset < 0 or end > len(raw):
            return {"ok": False, "error": "offset/patch out of range"}
        raw[offset:end] = patch
        return self._fs.write_bytes(path, bytes(raw))
