"""`python -m neoedge` — run a trade between simulated companies and print what NEOedge saw."""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

from .enrollment import DeviceEnrollment, EnrollmentError, bind_device
from .identity import load_or_create
from .matching import AGREED
from .testbed import build_network, run_trade

FAULTS = ("none", "missing_goods_receipt", "amount_mismatch", "partial_delivery",
          "duplicate_invoice", "silent_counterparty")


def demo(fault: str, companies: int) -> int:
    network = build_network(companies)
    buyer, seller = network[0], network[1]
    print(f"NEOedge testbed — {companies} simulated companies (semantics, not scale)\n")
    for company in network[:4]:
        print(f"  {company.member.legal_name:<22} {company.member_id:<32} on {company.system_id}")
    if companies > 4:
        print(f"  … and {companies - 4} more")

    result = run_trade(buyer, seller, "SLA-BR-2", fault=None if fault == "none" else fault)
    print(f"\ntrade  {buyer.member_id} (BUYER, {buyer.system_id})"
          f"\n    ×  {seller.member_id} (SELLER, {seller.system_id})"
          f"\n  contract SLA-BR-2 · relation {result.buyer_relation.ref[:16]}…"
          f"\n  fault injected: {fault}\n")

    for label, company, relation in (("buyer", buyer, result.buyer_relation),
                                     ("seller", seller, result.seller_relation)):
        snapshot = company.edge.seal("2026-07-20")
        sealed = "nothing to seal — silence is free" if snapshot is None else (
            f"root {snapshot.root[:16]}… over {snapshot.record_count} records")
        print(f"  {label:<7} book: {company.edge.book.height} records · snapshot: {sealed}")

    report = buyer.edge.review_against(seller.edge.records(result.seller_relation),
                                       result.buyer_relation)
    print(f"\n{report}\n")

    if result.events.get("duplicate_refused"):
        print(f"  the second invoice under the same number was refused: "
              f"{result.events['duplicate_refused']}\n")

    key = result.events.get("INVOICE")
    if key and buyer.edge.sealed:
        try:
            disclosure = buyer.edge.disclose(key)
        except KeyError:
            disclosure = None
        if disclosure is not None:
            size = 32 + 32 * len(disclosure.path)
            print(f"  disclosure for the invoice: leaf + {len(disclosure.path)} path hashes "
                  f"= {size} B · verifies offline: {disclosure.verify()}")

    verdict = "agreed on every event" if report.agreed else \
        f"{len(report.disagreements)} disputed event(s) — this is where a Chamber starts"
    print(f"\n  verdict: {verdict}")
    return 0 if report.agreed or fault != "none" else 1


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(prog="neoedge", description=__doc__)
    sub = parser.add_subparsers(dest="command")
    run = sub.add_parser("demo", help="run one trade between two simulated companies")
    run.add_argument("--fault", choices=FAULTS, default="none",
                     help="the dispute to inject (default: a clean trade)")
    run.add_argument("--companies", type=int, default=2,
                     help="how many companies to generate; the trade uses the first two")
    bind = sub.add_parser("bind-device", help="bind this install's device key to an existing Chamber member")
    bind.add_argument("--data", required=True)
    bind.add_argument("--chamber-url", default="https://chamber.cotrugli.tech")
    bind.add_argument("--member-id", required=True)
    bind.add_argument("--edge-id", required=True)
    bind.add_argument("--install-version", required=True)
    bind.add_argument("--install-hash", required=True)
    bind.add_argument("--capability", action="append", default=["neomark"])
    args = parser.parse_args(argv)
    if args.command == "demo":
        return demo(args.fault, args.companies)
    if args.command == "bind-device":
        identity = load_or_create(args.data)
        if identity is None:
            print("bind-device needs the cryptography signing extra", file=sys.stderr)
            return 2
        try:
            result = bind_device(args.chamber_url, DeviceEnrollment(
                args.member_id, args.edge_id, args.install_version, args.install_hash,
                tuple(args.capability)), identity)
        except EnrollmentError as error:
            print(f"DEVICE-BIND-STOP: {error}", file=sys.stderr)
            return 2
        target = Path(args.data) / "chamber-device-bind.json"
        target.write_text(json.dumps(result, sort_keys=True, indent=2) + "\n", encoding="utf-8")
        print(json.dumps({"status": "DEVICE_BOUND", "member_id": result["member_id"],
                          "decision_ref": result["decision_ref"]}))
        return 0
    parser.print_help()
    return 2


if __name__ == "__main__":
    sys.exit(main())
