#!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
import os
import sys

from codexpi.remote_ipc import remote_channel_request
from codexpi.remote_service import RemoteError, enqueue_remote_job


def main() -> int:
    parser = argparse.ArgumentParser(description="Accès fichier limité à une machine associée à CodexPi")
    parser.add_argument("--machine", help="identifiant de machine ; facultatif si une seule est associée")
    subparsers = parser.add_subparsers(dest="operation", required=True)
    subparsers.add_parser("machines")
    listing = subparsers.add_parser("list")
    listing.add_argument("path", nargs="?", default="")
    reading = subparsers.add_parser("read")
    reading.add_argument("path")
    writing = subparsers.add_parser("write")
    writing.add_argument("path")
    writing.add_argument("--expected", help="SHA-256 obtenu lors de la lecture, pour empêcher un écrasement concurrent")
    executing = subparsers.add_parser("exec")
    executing.add_argument("argv", nargs=argparse.REMAINDER)
    args = parser.parse_args()
    database = os.environ.get("CODEXPI_DATABASE", "/app/data/codexpi.db")
    remote_channel = os.environ.get("CODEXPI_REMOTE_CHANNEL")
    project_id = os.environ.get("CODEXPI_PROJECT_ID", "")
    if not project_id:
        print("Cette commande doit être lancée depuis une session de projet CodexPi.", file=sys.stderr)
        return 2
    try:
        if remote_channel:
            payload = None
            expected = None
            if args.operation == "write":
                if sys.stdin.isatty():
                    raise RemoteError("Le contenu du fichier doit être fourni sur l’entrée standard")
                payload = {"content": sys.stdin.read()}
                expected = args.expected
            elif args.operation == "exec":
                if not args.argv:
                    raise RemoteError("Indiquez la commande distante après exec")
                payload = {"argv": args.argv, "timeout": 120}
            result = remote_channel_request(remote_channel, {
                "operation": args.operation,
                "path": getattr(args, "path", ""),
                "payload": payload,
                "expected_hash": expected,
                "machine_id": args.machine,
            })
            if args.operation == "machines":
                print(json.dumps(result, ensure_ascii=False, indent=2))
                return 0
        elif args.operation == "machines":
            import sqlite3
            connection = sqlite3.connect(database)
            connection.row_factory = sqlite3.Row
            rows = connection.execute(
                "SELECT id,name,folder_name,platform,last_seen FROM remote_machines WHERE project_id=? AND revoked_at IS NULL ORDER BY last_seen DESC",
                (project_id,),
            ).fetchall()
            print(json.dumps([dict(row) for row in rows], ensure_ascii=False, indent=2))
            return 0
        else:
            payload = None
            expected = None
            if args.operation == "write":
                if sys.stdin.isatty():
                    raise RemoteError("Le contenu du fichier doit être fourni sur l’entrée standard")
                content = sys.stdin.read()
                payload = {"content": content}
                expected = args.expected
            elif args.operation == "exec":
                if not args.argv:
                    raise RemoteError("Indiquez la commande distante après exec")
                payload = {"argv": args.argv, "timeout": 120}
            result = enqueue_remote_job(
                database,
                project_id,
                args.operation,
                args.path,
                payload,
                expected,
                args.machine,
            )
        if args.operation == "read":
            sys.stdout.write(str(result.get("content", "")))
            if result.get("content") and not str(result["content"]).endswith("\n"):
                sys.stdout.write("\n")
            print(f"[sha256:{result.get('sha256','')}]", file=sys.stderr)
        else:
            print(json.dumps(result, ensure_ascii=False, indent=2))
        return 0
    except (RemoteError, OSError, ValueError) as exc:
        print(f"Erreur distante : {exc}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())
