#!/usr/bin/env python3
"""Quickstart: place a simulated call in test mode and read its results.

Requires Python 3.9+ and the requests package. Test mode never dials a real phone and never
charges anything.

    export RELATIONSAI_API_KEY="rai_test_..."
    export RELATIONSAI_API_BASE="https://voice-api.relationsai.com/v1"   # optional, this is the default
    python3 quickstart.py

Optional: RELATIONSAI_AGENT_ID=agent_... to use one of your own agents instead of the Sample agent.
"""
import json
import os
import sys
import time

import requests

api_key = os.environ.get("RELATIONSAI_API_KEY", "")
base_url = os.environ.get("RELATIONSAI_API_BASE", "https://voice-api.relationsai.com/v1").rstrip("/")

session = requests.Session()
session.headers["Authorization"] = f"Bearer {api_key}"


def api(method, path, body=None, params=None):
    r = session.request(method, f"{base_url}{path}", json=body, params=params, timeout=30)
    data = r.json()
    if not r.ok:
        e = data["error"]
        raise RuntimeError(f"{method} {path} failed with {r.status_code} {e['code']} (request {e['request_id']}): {e['message']}")
    return data


def main():
    # This script only ever runs in test mode.
    if not api_key.startswith("rai_test_"):
        raise RuntimeError("Set RELATIONSAI_API_KEY to a test key (rai_test_...). This quickstart never uses a live key.")

    # 1. Check the key: which workspace, which mode, which scopes.
    workspace = api("GET", "/workspace")
    if workspace["livemode"] is not False:
        raise RuntimeError("Expected a test-mode key (livemode false).")
    print(f"Workspace: {workspace['name']} (test mode), key \"{workspace['api_key']['name']}\"")
    if "calls:write" not in workspace["api_key"]["scopes"]:
        raise RuntimeError("This key cannot place calls. Create a test key with the calls:write scope.")

    # 2. Find an agent: the one you chose, or the built-in Sample agent.
    wanted = os.environ.get("RELATIONSAI_AGENT_ID")
    agent, cursor = None, None
    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor
        page = api("GET", "/agents", params=params)
        agent = next((a for a in page["data"] if (a["id"] == wanted if wanted else a["sample"])), None)
        cursor = page["next_cursor"] if page["has_more"] else None
        if agent or not cursor:
            break
    if not agent:
        raise RuntimeError("No matching agent found. Check the agent id.")
    print(f"Agent: {agent['name']} ({agent['id']})")

    # 3. Check that the agent can place calls right now.
    readiness = api("GET", f"/agents/{agent['id']}/readiness")
    if not readiness["ready"]:
        reasons = "; ".join(f"{r['code']}: {r['message']}" for r in readiness["reasons"])
        raise RuntimeError(f"The agent is not ready: {reasons}")

    # 4. Place a simulated call. +12025550100 answers and completes the conversation.
    # Sent once: if it times out, list your calls (GET /calls?to=...) before sending it again.
    created = api(
        "POST",
        "/calls",
        body={"agent_id": agent["id"], "to": "+12025550100", "metadata": {"source": "quickstart"}},
    )
    print(f"Call {created['id']} accepted: {created['status']}")

    # 5. Poll until the call is settled (about 30 seconds in test mode). In production, prefer webhooks.
    call = created
    deadline = time.monotonic() + 120
    while not call["settled"]:
        if time.monotonic() > deadline:
            raise RuntimeError(f"Call {call['id']} did not settle within 2 minutes.")
        time.sleep(3)
        nxt = api("GET", f"/calls/{call['id']}")
        if nxt["status"] != call["status"]:
            print(f"Status: {nxt['status']}")
        call = nxt
    cost = call["cost"]
    print(f"Settled: outcome {call['outcome']}, {call['duration_seconds']} s, cost {cost['amount']} {cost['currency']}")

    # 6. Read the results.
    transcript = api("GET", f"/calls/{call['id']}/transcript")
    print(f"Transcript ({transcript['state']}, {len(transcript['turns'])} turns):")
    for turn in transcript["turns"][:4]:
        print(f"  {turn['speaker']}: {turn['text']}")

    # The recording url is a short-lived credential: use it, but do not log or store it.
    recording = api("GET", f"/calls/{call['id']}/recording")
    print(f"Recording: {recording['state']}, {recording['content_type'] or 'no audio'}, link expires {recording['expires_at'] or 'n/a'}")

    analysis = api("GET", f"/calls/{call['id']}/analysis")
    print(f"Analysis: {analysis['state']}, goal met: {json.dumps(analysis['goal_met'])}")
    if analysis["summary"]["text"]:
        print(f"  Summary: {analysis['summary']['text']}")
    for field in analysis["extracted_fields"]:
        print(f"  {field['name']} = {json.dumps(field['value'])}")

    print("Done. Next: receive call.ended and call.settled by webhook instead of polling.")


if __name__ == "__main__":
    try:
        main()
    except (RuntimeError, requests.RequestException) as err:
        sys.exit(f"Error: {err}")
