"""
Client for the SIREN JSON-line protocol.
Works against both a plaintext local test instance and the real TLS target.
"""
import json
import socket
import ssl


class SirenClient:
    def __init__(self, host, port, use_tls=True, timeout=15):
        self.host = host
        self.port = port
        raw = socket.create_connection((host, port), timeout=timeout)
        if use_tls:
            ctx = ssl.create_default_context()
            ctx.check_hostname = False
            ctx.verify_mode = ssl.CERT_NONE
            self.sock = ctx.wrap_socket(raw, server_hostname=host)
        else:
            self.sock = raw
        self.rfile = self.sock.makefile("r", encoding="utf-8", newline="\n")
        banner = self.rfile.readline()
        self.banner = json.loads(banner) if banner.strip() else {}

    def _send(self, obj):
        line = (json.dumps(obj) + "\n").encode()
        self.sock.sendall(line)
        resp = self.rfile.readline()
        if not resp:
            raise ConnectionError("connection closed by server")
        return json.loads(resp)

    def pubkey(self):
        return self._send({"cmd": "pubkey"})

    def sign(self, msg):
        resp = self._send({"cmd": "sign", "msg": msg})
        if "error" in resp:
            raise RuntimeError(f"sign error: {resp['error']}")
        return int(resp["r"], 16), int(resp["s"], 16)

    def unlock(self, r, s):
        return self._send({"cmd": "unlock", "r": hex(r), "s": hex(s)})

    def close(self):
        try:
            self.sock.close()
        except Exception:
            pass
