import json
import os
import subprocess
import sys
import unittest
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
CLIENT = ROOT / "mcsj-swing-bridge-client.py"
PORT = os.environ.get("FX_AGENT_PORT", "9815")


class ClientV5LiveTests(unittest.TestCase):
    def test_fxstate_cli_prints_json(self):
        result = subprocess.run(
            [sys.executable, str(CLIENT), "--port", PORT, "fxstate"],
            capture_output=True, text=True, timeout=10,
        )
        self.assertEqual(result.returncode, 0, result.stderr)
        payload = json.loads(result.stdout)
        self.assertEqual(payload["status"], "OK")
        self.assertEqual(payload["panelCount"], 1)

    def test_fxfind_cli_scopes_node(self):
        result = subprocess.run(
            [sys.executable, str(CLIENT), "--port", PORT, "fxfind",
             "--panel-class", "javafx.scene.layout.VBox",
             "--class", "javafx.scene.control.TextField",
             "--id", "MyFxTextField"],
            capture_output=True, text=True, timeout=10,
        )
        self.assertEqual(result.returncode, 0, result.stderr)
        payload = json.loads(result.stdout)
        self.assertEqual(payload["count"], 1)
        self.assertEqual(payload["matches"][0]["id"], "MyFxTextField")

    def test_fxedittext_cli_mutates_and_verifies_then_restores(self):
        base = [sys.executable, str(CLIENT), "--port", PORT, "fxedittext",
                "--panel-class", "javafx.scene.layout.VBox",
                "--class", "javafx.scene.control.TextField",
                "--id", "MyFxTextField"]
        result = subprocess.run(base + ["--expected", "initial-value", "--new", "client-edited"],
                                capture_output=True, text=True, timeout=10)
        self.assertEqual(result.returncode, 0, result.stderr)
        payload = json.loads(result.stdout)
        self.assertEqual(payload["status"], "OK")
        self.assertEqual(payload["actual"], "client-edited")
        restore = subprocess.run(base + ["--expected", "client-edited", "--new", "initial-value"],
                                 capture_output=True, text=True, timeout=10)
        self.assertEqual(json.loads(restore.stdout)["status"], "OK")

    def test_fxtablecell_cli_selects_exact_cell(self):
        result = subprocess.run(
            [sys.executable, str(CLIENT), "--port", PORT, "fxtablecell",
             "--panel-class", "javafx.scene.layout.VBox",
             "--header", "Amount", "--row", "1", "--column", "1",
             "--action", "select", "--expected", "12.50"],
            capture_output=True, text=True, timeout=10,
        )
        self.assertEqual(result.returncode, 0, result.stderr)
        payload = json.loads(result.stdout)
        self.assertEqual(payload["status"], "OK")
        self.assertEqual(payload["selectedRow"], 1)
        self.assertEqual(payload["selectedColumn"], 1)

    def test_mutation_cli_returns_nonzero_for_stale_status(self):
        result = subprocess.run(
            [sys.executable, str(CLIENT), "--port", str(PORT), "fxedittext",
             "--panel-class", "javafx.scene.layout.VBox",
             "--class", "javafx.scene.control.TextField", "--id", "MyFxTextField",
             "--text", "initial-value", "--expected", "wrong-old-value", "--new", "never-written"],
            capture_output=True, text=True, timeout=10,
        )
        self.assertNotEqual(result.returncode, 0)
        payload = json.loads(result.stdout)
        self.assertEqual(payload["status"], "STALE")

    def test_raw_protocol_escape_hatch_is_not_exposed(self):
        result = subprocess.run(
            [sys.executable, str(CLIENT), "--port", str(PORT), "raw", "PING"],
            capture_output=True, text=True, timeout=10,
        )
        self.assertNotEqual(result.returncode, 0)


if __name__ == "__main__":
    unittest.main()
