#!/usr/bin/env python3
"""Consume one lighthouse unlock and execute one compiled-in local connector."""

import argparse
import json
import os
import subprocess
import sys
import urllib.error
import urllib.request


LIGHTHOUSE_URL = "http://127.0.0.1:8031"
FIXED_CONNECTORS = {
    (
        "AW-HLCC-CANDIDATE-DEPLOYER",
        "deploy_release",
        "AW-GZ-001",
    ): "/usr/local/libexec/guanghu/aw-hlcc-candidate-deploy",
}


def fail(message, code=2):
    print(message, file=sys.stderr)
    raise SystemExit(code)


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--unlock-id", required=True)
    parser.add_argument("--principal-id", required=True)
    parser.add_argument("--subject-kind", required=True, choices=("human", "persona", "persona_system"))
    parser.add_argument("--human-anchor", required=True)
    parser.add_argument("--agent-id", required=True)
    parser.add_argument("--action", required=True)
    parser.add_argument("--target-node-id", required=True)
    return parser.parse_args()


def consume_unlock(args, token):
    payload = json.dumps(
        {
            "unlock_id": args.unlock_id,
            "agent_id": args.agent_id,
            "action": args.action,
            "target_node_id": args.target_node_id,
        }
    ).encode()
    request = urllib.request.Request(
        LIGHTHOUSE_URL + "/v1/agents/consume",
        data=payload,
        method="POST",
        headers={
            "X-Lighthouse-Admin-Token": token,
            "Content-Type": "application/json",
            "X-Guanghu-Principal-Id": args.principal_id,
            "X-Guanghu-Subject-Kind": args.subject_kind,
            "X-Guanghu-Human-Anchor": args.human_anchor,
        },
    )
    try:
        with urllib.request.urlopen(request, timeout=10) as response:
            body = json.load(response)
    except urllib.error.HTTPError as error:
        fail("Lighthouse rejected the connector request with HTTP %d." % error.code, 4)
    except (OSError, ValueError) as error:
        fail("Lighthouse connector request failed: %s" % error, 4)
    if not body.get("ok") or not body.get("consumed"):
        fail("Lighthouse did not return a consumed Agent unlock.", 4)


def main():
    if os.geteuid() != 0:
        fail("The fixed connector must be invoked by root.", 3)
    args = parse_args()
    key = (args.agent_id, args.action, args.target_node_id)
    executable = FIXED_CONNECTORS.get(key)
    if not executable:
        fail("No fixed local connector is registered for this Agent/action/target.", 3)
    token = os.environ.get("LIGHTHOUSE_ADMIN_TOKEN", "")
    if not token:
        fail("LIGHTHOUSE_ADMIN_TOKEN is required but must not be passed on the command line.", 3)
    if not os.path.isfile(executable) or not os.access(executable, os.X_OK):
        fail("The registered fixed local connector is unavailable.", 3)
    consume_unlock(args, token)
    completed = subprocess.run([executable], check=False)
    raise SystemExit(completed.returncode)


if __name__ == "__main__":
    main()
