"""CacheVerifier quickstart -- a runnable version of the worked example on
https://www.cacheverifier.com/docs#integration, callable directly against
the live API. No dependencies beyond `requests` (pip install requests).

Set CACHEVERIFIER_API_KEY in your environment if you already have one,
otherwise this script registers a free tenant for you -- self-serve verify
and fine-tuning are free forever, no card required
(see https://www.cacheverifier.com/pricing).

    CACHEVERIFIER_API_KEY=cv_... python quickstart.py
"""

import os

import requests

BASE_URL = "https://www.cacheverifier.com"


def get_api_key() -> str:
    api_key = os.environ.get("CACHEVERIFIER_API_KEY")
    if api_key:
        return api_key

    print("No CACHEVERIFIER_API_KEY set in your environment -- registering a free tenant.")
    email = input("Email: ").strip()
    password = input("Password (min 8 chars): ").strip()
    resp = requests.post(
        f"{BASE_URL}/v1/auth/register",
        json={"email": email, "password": password, "tenant_name": email.split("@")[0]},
    )
    resp.raise_for_status()
    api_key = resp.json()["api_key"]
    print(f"\nRegistered. This is your API key -- it's only ever shown once, save it:\n  {api_key}\n")
    return api_key


def call_real_llm(query: str) -> str:
    """Stand-in for whatever your own LLM call looks like -- CacheVerifier
    doesn't do this part, your cache backend already has one."""
    return "Go to Settings > Billing > Cancel subscription."


def main() -> None:
    headers = {"X-API-Key": get_api_key()}

    # A gray-zone example: your cache's similarity search found a candidate
    # close enough to look like a match, but "cancel" and "pause" are a real
    # difference a plain similarity threshold can't tell apart.
    user_query = "how do I cancel my subscription"
    candidate_answer = "Go to Settings > Billing > Pause subscription for a month."

    print(f"query:     {user_query!r}")
    print(f"candidate: {candidate_answer!r}  (from your cache, similarity 0.86)\n")

    verify = requests.post(
        f"{BASE_URL}/v1/verify",
        headers=headers,
        json={"query": user_query, "candidate_answer": candidate_answer},
    ).json()
    print(f"POST /v1/verify -> {verify}\n")

    if verify.get("approved"):
        answer = candidate_answer  # cache hit confirmed -- skip the LLM call
        print("approved: serving the cached answer, no LLM call made.")
    else:
        answer = call_real_llm(user_query)  # not trustworthy -- fall through, then re-cache
        print(f"rejected: fell through to a real LLM call -> {answer!r}")

    # Once you know the real outcome (a thumbs-down, a support ticket
    # reopening, manual review, ...) report it back -- this is what
    # POST /v1/finetune/jobs and GET /v1/monitor/drift-status both learn
    # from. It's correct either way here: a rejected candidate fell through
    # to a fresh LLM answer, and an approved one was the verified hit.
    feedback = requests.post(
        f"{BASE_URL}/v1/feedback",
        headers=headers,
        json={"query": user_query, "candidate_answer": answer, "was_correct": True},
    ).json()
    print(f"\nPOST /v1/feedback -> {feedback}")

    print(
        "\nNext: repeat this loop on your own gray-zone traffic. Once you have a couple\n"
        "hundred labeled rows, POST /v1/finetune/jobs trains a tenant-specific verifier --\n"
        "full reference at https://www.cacheverifier.com/docs"
    )


if __name__ == "__main__":
    main()
