import json, pathlib, re, subprocess, time, urllib.error, urllib.request

ENDPOINT = 'http://127.0.0.1:8787'
_PATTERN = 'IGGY_SHARED_' + 'SECRET' + '=' + r'(\S+)'


def get_secret_and_sessions():
    ps = subprocess.check_output(['ps', 'eww', '-ax'], text=True, errors='ignore')
    candidates = []
    for line in ps.splitlines():
        if 'server.mjs' not in line:
            continue
        candidates.extend(re.findall(_PATTERN, line))
    for secret in dict.fromkeys(candidates):
        try:
            req = urllib.request.Request(f'{ENDPOINT}/sessions', headers={'Authorization': 'Bearer ' + secret})
            with urllib.request.urlopen(req, timeout=5) as r:
                data = json.loads(r.read().decode())
            if data.get('ok'):
                return secret, data.get('sessions') or []
        except Exception:
            pass
    raise RuntimeError('No working relay secret found')


def best_session(sessions):
    # Prefer the real KRB Designer iframe session over local standalone /code tabs.
    def score(s):
        ctx = s.get('context') or {}
        site = ctx.get('site') or {}
        url = ctx.get('url') or ''
        has_designer_api = bool(((ctx.get('diagnostics') or {}).get('webflowGlobals') or {}).get('hasWebflowDesignerApi'))
        return (
            10 if s.get('userId') == 'sylvain' else 0,
            20 if site.get('shortName') == 'krb-rebuild' or site.get('name') == 'Kincoppal-Rose Bay' else 0,
            10 if has_designer_api else 0,
            -5 if url.endswith('/code') else 0,
            s.get('lastSeenAt') or '',
        )
    candidates = [s for s in sessions if s.get('userId') == 'sylvain'] or sessions
    candidates.sort(key=score, reverse=True)
    return candidates[0]['sessionId']


def queue_file(path, session_id=None, wait=True, timeout=160):
    secret, sessions = get_secret_and_sessions()
    session_id = session_id or best_session(sessions)
    code = pathlib.Path(path).read_text()
    body = {'code': code, 'dangerous': False, 'requiresConfirmation': False, 'reply': f'Executing {path} via direct Designer relay.'}
    req = urllib.request.Request(f'{ENDPOINT}/sessions/{session_id}/commands', data=json.dumps(body).encode(), headers={'Authorization': 'Bearer ' + secret, 'Content-Type': 'application/json'}, method='POST')
    with urllib.request.urlopen(req, timeout=10) as r:
        queued = json.loads(r.read().decode())
    command_id = queued.get('commandId') or queued.get('command', {}).get('commandId')
    if not wait:
        return {'sessionId': session_id, 'commandId': command_id, 'queued': queued}
    deadline = time.time() + timeout
    while time.time() < deadline:
        time.sleep(1)
        result = get_result(session_id, command_id, secret=secret)
        if result is not None:
            return result
    raise TimeoutError(f'No result for {command_id} after {timeout}s')


def get_result(session_id, command_id, secret=None):
    if secret is None:
        secret, _ = get_secret_and_sessions()
    req = urllib.request.Request(f'{ENDPOINT}/sessions/{session_id}/commands/{command_id}/result', headers={'Authorization': 'Bearer ' + secret})
    try:
        with urllib.request.urlopen(req, timeout=5) as r:
            return json.loads(r.read().decode())
    except urllib.error.HTTPError as e:
        if e.code == 404:
            return None
        raise

if __name__ == '__main__':
    import sys
    secret, sessions = get_secret_and_sessions()
    if len(sys.argv) == 1:
        print(json.dumps({'sessions': [{k:s.get(k) for k in ['sessionId','userId','status','lastSeenAt']} for s in sessions]}, indent=2))
    elif sys.argv[1] == 'result':
        print(json.dumps(get_result(sys.argv[2], sys.argv[3], secret=secret), indent=2))
    else:
        out = queue_file(sys.argv[1])
        print(json.dumps(out, indent=2))
