#!/usr/bin/env python3
# SPDX-License-Identifier: AGPL-3.0-only
"""Faux harnais "claude" du banc de test — n'appelle jamais Claude Code.

Émet le même flux JSONL que `claude -p --output-format stream-json`, journalise
son argv dans $AMEESH_TEST_LOG, et obéit à deux variables de banc :
AMEESH_TEST_SLEEP (secondes de sommeil) et AMEESH_TEST_EXIT (code) ; L223:
AMEESH_TEST_CLAUDE_HELP (text printed by `--help`) ; L105 :
AMEESH_TEST_CLAUDE_CALLS (JSON : appels au modèle, jetons relus, outil, durée ;
L217 : `parent`, l'outil du fil principal dont l'appel est un sous-agent).
Travail de fond : AMEESH_TEST_BACKGROUND (commande shell lancée en fond, dans
le groupe du tour, que le harnais n'attend pas) et AMEESH_TEST_BACKGROUND_PID
(fichier où écrire son pid). L217b : AMEESH_TEST_CLAUDE_ON_TERM (JSON : un
appel du fil principal émis à la réception de SIGTERM, donc lu après la
clôture du tour, comme un appel encore en tampon).
"""
import json
import os
import signal
import sys
import time


def _compte() -> dict:
    """Le compte vu par le harnais (L30) : dossiers, et l'EMPREINTE de la clé
    (jamais la clé, même factice)."""
    import hashlib
    cle = os.environ.get("DEEPSEEK_API_KEY")
    return {
        "CLAUDE_CONFIG_DIR": os.environ.get("CLAUDE_CONFIG_DIR"),
        "CODEX_HOME": os.environ.get("CODEX_HOME"),
        "DSH_HOME": os.environ.get("DSH_HOME"),
        "cle": hashlib.sha256(cle.encode()).hexdigest()[:12] if cle else None,
    }


def main() -> int:
    args = sys.argv[1:]
    if args == ["--version"]:  # L120: read by the runner, not a turn
        print("9.9.9 (Claude Code, fake)")
        return 0
    if args == ["--help"]:
        # L223: the help read for the interactive permission mode, before any
        # log (it is not a turn); AMEESH_TEST_CLAUDE_HELP simulates an older
        # version
        print(os.environ.get("AMEESH_TEST_CLAUDE_HELP", '  --permission-mode <mode>  '
              '(choices: "acceptEdits", "auto", "bypassPermissions", "manual", '
              '"dontAsk", "plan")'))
        return 0
    log = os.environ.get("AMEESH_TEST_LOG")
    if log:
        with open(log, "a", encoding="utf-8") as fh:
            fh.write(json.dumps({
                "harness": "claude", "argv": args, "compte": _compte(),
                "env": {k: os.environ.get(k) for k in (
                    "AGENT_MAIL_NAME", "AMEESH_RUNNER_ID", "AGENT_MESH_RUNNER_ID",
                    "AMEESH_LEASE_EPOCH", "AGENT_MESH_LEASE_EPOCH",
                    "AMEESH_HOST", "AMEESH_SCHEMA", "AMEESH_TURN_MAIL_MAX",
                    "AMEESH_TURN_ID", "AMEESH_HARNESS",
                    # #834 : l'identité git de la session (auteur et committer)
                    "GIT_AUTHOR_NAME", "GIT_AUTHOR_EMAIL",
                    "GIT_COMMITTER_NAME", "GIT_COMMITTER_EMAIL",
                    # L73 : dossier temporaire et caches gérés
                    "TMPDIR", "TMP", "TEMP", "AMEESH_TMPDIR", "AMEESH_CACHE_DIR",
                    "npm_config_cache", "npm_config_store_dir", "YARN_CACHE_FOLDER")},
            }) + "\n")
    if os.environ.get("AMEESH_TEST_MAKE_TMP"):
        # L73 : un tour qui laisse des fichiers dans son TMPDIR et une entrée
        # dans le /tmp du système (chemin donné), comme un clone de relecture
        import tempfile
        with tempfile.NamedTemporaryFile(delete=False, prefix="tour-") as fh:
            fh.write(b"x" * 4096)
        dehors = os.environ["AMEESH_TEST_MAKE_TMP"]
        os.makedirs(dehors, exist_ok=True)
        with open(os.path.join(dehors, "gros"), "wb") as fh:
            fh.write(b"y" * 200_000)
    if os.environ.get("AMEESH_TEST_BACKGROUND"):
        # un travail lancé en fond pendant le tour (comme `cmd &` d'un outil) :
        # même groupe, sorties détournées (un vrai harnais capture celles de
        # ses outils), jamais attendu par le harnais
        import subprocess
        fond = subprocess.Popen(["sh", "-c", os.environ["AMEESH_TEST_BACKGROUND"]],
                                stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
                                stderr=subprocess.DEVNULL)
        if os.environ.get("AMEESH_TEST_BACKGROUND_PID"):
            with open(os.environ["AMEESH_TEST_BACKGROUND_PID"], "w", encoding="utf-8") as fh:
                fh.write(str(fond.pid))
    if os.environ.get("AMEESH_TEST_RUN"):
        # L123 : une commande lancée DANS la session, comme par l'outil Bash
        # du harnais (`ameesh chat` de bout en bout) ; son résultat au journal
        import subprocess
        proc = subprocess.run(os.environ["AMEESH_TEST_RUN"], shell=True,
                              capture_output=True, text=True)
        if log:
            with open(log, "a", encoding="utf-8") as fh:
                fh.write(json.dumps({"harness": "claude", "run": {
                    "code": proc.returncode, "stdout": proc.stdout,
                    "stderr": proc.stderr}}) + "\n")
    if os.environ.get("AMEESH_TEST_SLEEP"):
        time.sleep(float(os.environ["AMEESH_TEST_SLEEP"]))
    if os.environ.get("AMEESH_TEST_KILL_SELF"):
        os.kill(os.getpid(), signal.SIGKILL)
    # #408 : une session neuve peut porter un autre id (une session par lot)
    session = os.environ.get("AMEESH_TEST_NEW_SESSION") or "claude-sess-1"
    if "--resume" in args:
        session = args[args.index("--resume") + 1]
    print(json.dumps({"type": "system", "subtype": "init", "session_id": session,
                      "cwd": os.getcwd()}), flush=True)
    if os.environ.get("AMEESH_TEST_CLAUDE_ON_TERM"):
        tampon = json.loads(os.environ["AMEESH_TEST_CLAUDE_ON_TERM"])

        def _sur_term(_signum, _frame):
            relus = int(tampon.get("reread", 0))
            print(json.dumps({"type": "assistant", "parent_tool_use_id": None,
                              "session_id": session, "message": {
                                  "id": "msg-tampon", "content": [{"type": "text", "text": "tampon"}],
                                  "usage": {"input_tokens": relus // 10,
                                            "cache_read_input_tokens": relus - relus // 10,
                                            "output_tokens": 10}}}), flush=True)
            sys.exit(143)

        signal.signal(signal.SIGTERM, _sur_term)
    if os.environ.get("AMEESH_TEST_RATE_LIMIT"):
        # relevé de jauge enregistré (L30) : rejoué tel quel dans le flux
        print(json.dumps({"type": "rate_limit_event", "rate_limit_info": {
            "unifiedWindows": json.loads(os.environ["AMEESH_TEST_RATE_LIMIT"])}}), flush=True)
    appels = json.loads(os.environ.get("AMEESH_TEST_CLAUDE_CALLS") or "[]")
    # L221 : le `result` porte l'usage du tour, comme le vrai flux
    tour = {"input_tokens": 100, "cache_read_input_tokens": 0, "output_tokens": 20}
    for index, appel in enumerate(appels):
        # L105 : un appel au modèle — usage par message (répété sur chaque bloc,
        # comme le vrai flux), puis, s'il appelle un outil, son résultat
        relus = int(appel.get("reread", 0))
        usage = {"input_tokens": relus // 10, "cache_read_input_tokens": relus - relus // 10,
                 "output_tokens": 10}
        message = {"id": "msg-%d" % index, "usage": usage}
        for cle, valeur in usage.items():
            tour[cle] += valeur
        # L217 : `parent` = appel d'un sous-agent, lancé par cet outil du fil
        # principal (comme le vrai flux : `parent_tool_use_id`, nul sinon)
        fil = {"parent_tool_use_id": appel.get("parent"), "session_id": session}
        print(json.dumps(dict(fil, type="assistant", message=dict(message, content=[
            {"type": "text", "text": "appel %d" % index}]))), flush=True)
        if appel.get("tool"):
            print(json.dumps(dict(fil, type="assistant", message=dict(message, content=[
                {"type": "tool_use", "id": "outil-%d" % index, "name": "x", "input": {}}]))),
                flush=True)
            time.sleep(float(appel.get("sleep", 0)))
            print(json.dumps(dict(fil, type="user", message={"role": "user", "content": [
                {"type": "tool_result", "tool_use_id": "outil-%d" % index,
                 "content": "ok"}]})), flush=True)
    # L218 : AMEESH_TEST_RESULT, la réponse du tour (message et `result`)
    reponse = os.environ.get("AMEESH_TEST_RESULT")
    if reponse is None:
        reponse_texte, reponse = "bonjour du faux claude (session %s)" % session, "fini"
    else:
        reponse_texte = reponse  # vide compris : un tour sans réponse
    print(json.dumps({"type": "assistant", "message": {"content": [
        {"type": "text", "text": reponse_texte}]}}), flush=True)
    print(json.dumps({"type": "result", "subtype": "success", "result": reponse,
                      "total_cost_usd": 0.0125, "usage": tour, "session_id": session}),
          flush=True)
    return int(os.environ.get("AMEESH_TEST_EXIT", "0"))


if __name__ == "__main__":
    sys.exit(main())
