#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
KKOS SDK — runnable example (standard library only).

What it does
------------
1. Opens a text-mode modelling session.
2. Sends three user turns and prints each reply as it arrives.
3. Completes the session, which builds the 11-dimension model.
4. Prints every dimension with its score, confidence and evidence.

Usage
-----
    python example.py
    KKOS_API_KEY=kk_live_xxxxxxxx python example.py
    KKOS_TOKEN=<user token> python example.py --base http://127.0.0.1:8001
    python example.py --json > model.json     # dump the raw model instead

Auth note
---------
The session endpoints (`/mirror/start|message|complete`) are login-gated: they
need a *user token* (`Authorization: Bearer <uid>.<ts>.<sig>`), not just an API
key. A platform API key is enough for `health`, `plans`, `voices` and the other
open endpoints. Pass `--token`, or `--both` to send both credentials.
"""

import argparse
import json
import os
import sys
import textwrap

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from kkos_client import KKOS, KKOSError  # noqa: E402

DEFAULT_LINES = [
    "I usually decide fast and say what I think, even if it is blunt.",
    "When someone around me hesitates, I tend to push them toward a decision.",
    "I would rather get a direct answer than a polite one, honestly.",
]

DIM_ZH = {
    "communication_style": "沟通风格",
    "directness": "直接性",
    "openness": "开放性",
    "engagement": "投入度",
    "decision_style": "决策风格",
    "uncertainty_response": "不确定应对",
    "reflection_style": "反思风格",
    "conflict_style": "冲突风格",
    "trust_disclosure_pattern": "信任披露",
    "emotional_expression": "情绪表达",
    "ai_interaction_style": "与 AI 互动",
}


def bar(value, width=24):
    try:
        filled = int(round(float(value) / 100.0 * width))
    except (TypeError, ValueError):
        filled = 0
    return "#" * max(0, min(width, filled)) + "." * (width - max(0, min(width, filled)))


def main(argv=None):
    ap = argparse.ArgumentParser(description="KKOS SDK runnable example")
    ap.add_argument("--base", default=os.environ.get("KKOS_BASE_URL", "https://kkmatch.com"),
                    help="API base URL (default: https://kkmatch.com)")
    ap.add_argument("--key", default=os.environ.get("KKOS_API_KEY"),
                    help="platform API key (default: $KKOS_API_KEY)")
    ap.add_argument("--token", default=os.environ.get("KKOS_TOKEN"),
                    help="user session token (default: $KKOS_TOKEN)")
    ap.add_argument("--lines", type=int, default=0, help="use only the first N lines")
    ap.add_argument("--json", action="store_true", help="print the raw model JSON")
    ap.add_argument("--keep", action="store_true", help="do not delete the model afterwards")
    args = ap.parse_args(argv)

    if not args.key and not args.token:
        print("!! no credentials. Set KKOS_API_KEY / KKOS_TOKEN, or pass --key / --token.",
              file=sys.stderr)
        print("   Create an API key at https://kkmatch.com/account.html", file=sys.stderr)
        return 2

    kk = KKOS(api_key=args.key, token=args.token, base_url=args.base)
    lines = DEFAULT_LINES[:args.lines] if args.lines else DEFAULT_LINES

    if not args.json:
        print("=" * 66)
        print("KKOS SDK example  ·  base=%s" % args.base)
        print("=" * 66)
        try:
            h = kk.health()
            print("health: %s" % (h.get("status", h) if isinstance(h, dict) else h))
        except KKOSError as e:
            print("health check failed: %s" % e, file=sys.stderr)

    def on_reply(i, text):
        if args.json:
            return
        print("\n[turn %d] user: %s" % (i + 1, lines[i]))
        wrapped = textwrap.fill((text or "(empty)").strip(), 62,
                                initial_indent="        ai: ", subsequent_indent="            ")
        print(wrapped)

    try:
        model = kk.run_text_session(lines, on_reply=on_reply)
    except KKOSError as e:
        print("\n!! API error: %s" % e, file=sys.stderr)
        return 1

    if args.json:
        print(json.dumps(model, ensure_ascii=False, indent=2))
        return 0

    traits = model.get("traits") or []
    print("\n" + "=" * 66)
    print("MODEL  id=%s  version=%s  overall_confidence=%s"
          % (model.get("model_id", "?"), model.get("model_version", "?"),
             model.get("overall_confidence", "?")))
    print("=" * 66)
    if not traits:
        print("(no traits returned)")
    for t in traits:
        name = t.get("name", "?")
        print("  %-24s %-16s %s  score=%3s conf=%s"
              % (name, DIM_ZH.get(name, ""), bar(t.get("score")),
                 t.get("score"), t.get("confidence")))
    summary = model.get("summary")
    if summary:
        print("\nsummary:\n%s" % textwrap.fill(str(summary), 64,
                                                initial_indent="  ", subsequent_indent="  "))
    ev = None
    for t in traits:
        if t.get("evidence"):
            ev = (t["name"], t["evidence"])
            break
    if ev:
        print("\nevidence example (%s):\n  - %s" % (ev[0], "\n  - ".join(map(str, ev[1][:3]))))

    manual = model.get("communication_manual")
    if manual:
        print("\ncommunication manual:\n%s" % textwrap.fill(str(manual), 64,
                                                              initial_indent="  ", subsequent_indent="  "))

    cost = model.get("cost")
    if isinstance(cost, dict) and cost:
        print("\ncost: %s tokens in / %s out over %s llm calls · est. $%s"
              % (cost.get("llm_in_tokens"), cost.get("llm_out_tokens"),
                 cost.get("llm_calls"), cost.get("estimated_usd")))

    mid = model.get("model_id")
    if mid and not args.keep:
        try:
            kk.delete_model(mid)
            print("\n(example model %s deleted — pass --keep to retain it)" % mid[:8])
        except KKOSError as e:
            print("\n(cleanup skipped: %s)" % e, file=sys.stderr)
    print("\nDone. Full API reference: https://kkmatch.com/sdk/")
    return 0


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