#!/usr/bin/env python3
"""Example: async echo bot using the quicproquo Python SDK.

Connects to a qpq server, authenticates, and echoes back any received
messages with a "[bot] " prefix.

Usage:
    python bot.py --server 127.0.0.1:5001 --ca-cert ca.pem

This example uses the QUIC transport with the v2 wire format.
OPAQUE authentication requires external crypto; this demo assumes
a session token is obtained externally and set via --token.
"""

from __future__ import annotations

import argparse
import asyncio
import signal
import sys

from quicproquo import QpqClient, ConnectOptions


async def run_bot(opts: ConnectOptions, token: bytes, identity_key: bytes) -> None:
    client = await QpqClient.connect(opts)
    client.set_session_token(token)

    print(f"Connected to {opts.addr}")

    health = await client.health()
    print(f"Server status: {health.status} (v{health.version})")

    # Poll loop.
    running = True

    def on_signal() -> None:
        nonlocal running
        running = False
        print("\nShutting down...")

    loop = asyncio.get_running_loop()
    for sig in (signal.SIGINT, signal.SIGTERM):
        loop.add_signal_handler(sig, on_signal)

    while running:
        try:
            messages = await client.receive_wait(
                identity_key, timeout_ms=5000
            )
        except Exception as exc:
            print(f"receive error: {exc}")
            await asyncio.sleep(1)
            continue

        for msg in messages:
            text = msg.data.decode("utf-8", errors="replace")
            print(f"[seq={msg.seq}] {text}")

            # Echo back with prefix.
            echo = f"[bot] {text}".encode("utf-8")
            try:
                seq, _ = await client.send(identity_key, echo)
                print(f"  -> echoed (seq={seq})")
            except Exception as exc:
                print(f"  -> send error: {exc}")

    await client.close()
    print("Disconnected.")


def main() -> None:
    parser = argparse.ArgumentParser(description="qpq echo bot")
    parser.add_argument("--server", default="127.0.0.1:5001", help="server address")
    parser.add_argument("--ca-cert", default="", help="CA certificate path")
    parser.add_argument("--server-name", default="", help="TLS server name")
    parser.add_argument("--token", required=True, help="session token (hex)")
    parser.add_argument("--identity-key", required=True, help="identity key (hex)")
    parser.add_argument("--insecure", action="store_true", help="skip TLS verification")
    args = parser.parse_args()

    opts = ConnectOptions(
        addr=args.server,
        ca_cert_path=args.ca_cert,
        server_name=args.server_name,
        insecure_skip_verify=args.insecure,
    )

    token = bytes.fromhex(args.token)
    identity_key = bytes.fromhex(args.identity_key)

    asyncio.run(run_bot(opts, token, identity_key))


if __name__ == "__main__":
    main()
