#!/usr/bin/env python3
"""Provision a GitHub/Grafana integration with secrets, attach an agent, Ask.

Happy path uses ``upsert_integration_with_secrets`` so the SDK resolves Vault
metadata keys from a plain secrets map, stores the secret, binds
``secret_ref_ids``, and upserts the integration in one call. Then
register/update an agent that uses that integration and optionally start Ask
with ``mode``.

Env:
  STACKGEN_URL, STACKGEN_TOKEN, STACKGEN_WORKSPACE_ID (required)
  GH_TOKEN or GITHUB_TOKEN — prefer GitHub integration
  GRAFANA_BASE_URL + GRAFANA_API_TOKEN — else Grafana
  Without vendor tokens, uses a synthetic GitHub token + skip connectivity
  (fine for CI shape checks; not a live vendor connection).

Usage:
  python examples/automation/agent-vault-ask.py
  python examples/automation/agent-vault-ask.py --ask --mode simple
"""

from __future__ import annotations

import argparse
import os
import sys
import uuid

from stackgen import StackgenClient, StackgenConfig


def env(name: str, *fallbacks: str) -> str:
    for key in (name, *fallbacks):
        value = (os.environ.get(key) or "").strip()
        if value:
            return value
    raise SystemExit(f"missing env {name}")


def optional_env(*names: str) -> str:
    for name in names:
        value = (os.environ.get(name) or "").strip()
        if value:
            return value
    return ""


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--ask",
        action="store_true",
        help="Also start Ask against the agent (mode defaults to simple)",
    )
    parser.add_argument(
        "--mode",
        default="simple",
        choices=("simple", "plan"),
        help="Ask mode pin when --ask is set",
    )
    args = parser.parse_args()

    client = StackgenClient(
        StackgenConfig(
            base_url=env("STACKGEN_URL"),
            api_token=env("STACKGEN_TOKEN"),
            workspace_id=env("STACKGEN_WORKSPACE_ID", "STACKGEN_PROJECT"),
        )
    )

    suffix = uuid.uuid4().hex[:8]
    integration_name = f"sdk-int-{suffix}"
    agent_name = f"sdk-agent-{suffix}"
    secret_ids: list[str] = []

    gh_token = optional_env("GH_TOKEN", "GITHUB_TOKEN")
    grafana_url = optional_env("GRAFANA_BASE_URL", "STACKGEN_GRAFANA_BASE_URL")
    grafana_token = optional_env("GRAFANA_API_TOKEN", "STACKGEN_GRAFANA_API_TOKEN")

    try:
        # --- Happy path: Vault + bind + upsert in one helper ---
        if gh_token:
            provisioned = client.aiden.upsert_integration_with_secrets(
                integration_name,
                type="github",
                secrets={"token": gh_token},
                description="sdk sample GitHub integration",
                skip_connectivity_check=True,
            )
            print(f"upsert_integration_with_secrets type=github name={integration_name}")
        elif grafana_url and grafana_token:
            provisioned = client.aiden.upsert_integration_with_secrets(
                integration_name,
                type="grafana",
                secrets={"base_url": grafana_url, "api_token": grafana_token},
                description="sdk sample Grafana integration",
                skip_connectivity_check=True,
            )
            print(f"upsert_integration_with_secrets type=grafana name={integration_name}")
        else:
            # CI / local without vendor tokens: still exercise the combined helper.
            provisioned = client.aiden.upsert_integration_with_secrets(
                integration_name,
                type="github",
                secrets={"token": f"sdk-sample-not-a-real-token-{suffix}"},
                description="sdk sample GitHub binding (synthetic token)",
                skip_connectivity_check=True,
            )
            print(
                f"upsert_integration_with_secrets type=github name={integration_name} "
                "(synthetic token; set GH_TOKEN for a real binding)"
            )

        secret_ids = list(provisioned.get("secret_ids") or [])
        print(f"secret_ids={secret_ids}")

        # Advanced (granular) alternative — store then bind yourself:
        #   secret = client.vault.store_github_secret(name=..., token=...)
        #   client.aiden.upsert_integration(
        #       integration_name,
        #       {
        #           "type": "github",
        #           "description": "...",
        #           "scope": "TENANT",
        #           "enabled": True,
        #           "secret_ref_ids": [secret["id"]],
        #       },
        #   )

        detail = client.aiden.get_integration(integration_name, include_tools=True)
        tools = detail.get("discovered_tools") or detail.get("tools") or []
        print(
            f"get_integration name={integration_name} "
            f"tools={len(tools) if isinstance(tools, list) else 'n/a'}"
        )

        client.aiden.register_agent(
            {
                "name": agent_name,
                "persona": "Ops assistant. Prefer integration tool evidence.",
                "description": "sdk sample agent wired to a Vault-backed integration",
                "integrations": [integration_name],
                "world_model_enabled": False,
                "hitl": {"always_allowed": ["*"]},
            }
        )
        print(f"register_agent name={agent_name} integrations=[{integration_name}]")

        client.aiden.update_agent(
            agent_name,
            {
                "description": "sdk sample agent (updated)",
                "integrations": [integration_name],
            },
        )
        print("update_agent ok")

        if args.ask:
            start = client.aiden.start_ask(
                "SDK sample: reply with one short sentence about your tools.",
                entity_refs=[{"name": agent_name, "type": "agent"}],
                mode=args.mode,
            )
            print(
                f"start_ask mode={args.mode} trace_id={start.get('trace_id')} "
                f"session_id={start.get('session_id')}"
            )
    finally:
        try:
            client.aiden.deregister_agent(agent_name)
            print(f"deregister_agent name={agent_name}")
        except Exception as err:  # noqa: BLE001
            print(f"deregister_agent failed: {err}", file=sys.stderr)
        try:
            client.aiden.delete_integration(integration_name)
            print(f"delete_integration name={integration_name}")
        except Exception as err:  # noqa: BLE001
            print(f"delete_integration failed: {err}", file=sys.stderr)
        for secret_id in secret_ids:
            try:
                client.vault.delete_secret(secret_id)
                print(f"delete_secret id={secret_id}")
            except Exception as err:  # noqa: BLE001
                print(f"delete_secret failed: {err}", file=sys.stderr)

    return 0


if __name__ == "__main__":
    raise SystemExit(main())
