"""Аудит ИИ VakHunter: живой прогон каждой модели (primary 70b, fast 8b,
fallback-цепочка) + проверка реального переключения на фоллбэк + сквозной
прогон реальных AI-функций (cover letter, career Q&A, score, parse)."""
import asyncio
import os
import sys
import time

os.chdir(os.path.expanduser("~/Services/VakHunter"))
sys.path.insert(0, ".")

# env из .env
for ln in open(".env", encoding="utf-8"):
    ln = ln.strip()
    if "=" in ln and not ln.startswith("#"):
        k, v = ln.split("=", 1)
        os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'"))

from bot.ai_assistant import AIAssistant  # noqa: E402

PASS, FAIL = [], []


def ck(name, ok, detail=""):
    (PASS if ok else FAIL).append(name)
    print(("✅" if ok else "❌"), name, ("— " + str(detail)[:180]) if detail else "")


async def main():
    ai = AIAssistant()
    print("primary base:", ai.base_url)
    print("primary model:", ai.model)
    print("fast model:", ai.fast_model)
    fb_base = os.getenv("FALLBACK_API_BASE"); fb_models = os.getenv("FALLBACK_MODEL")
    print("fallback base:", fb_base, "| models:", fb_models)
    msgs = [{"role": "user", "content": "Ответь одним словом: столица Франции?"}]

    # ── 1. Каждый провайдер напрямую (латентность + непустой ответ) ──
    print("\n─── прямой вызов каждой модели ───")
    # primary 70b
    t = time.time()
    try:
        r = await ai._call_provider(ai.base_url, ai.api_key, ai.model, msgs, 0.2, 64, 40.0)
        ck(f"primary {ai.model}", bool(r and r.strip()), f"{time.time()-t:.1f}s → {r!r}")
    except Exception as e:
        ck(f"primary {ai.model}", False, f"EXC {type(e).__name__}: {e}")
    # fast 8b
    t = time.time()
    try:
        r = await ai._call_provider(ai.base_url, ai.api_key, ai.fast_model, msgs, 0.2, 64, 40.0)
        ck(f"fast {ai.fast_model}", bool(r and r.strip()), f"{time.time()-t:.1f}s → {r!r}")
    except Exception as e:
        ck(f"fast {ai.fast_model}", False, f"EXC {type(e).__name__}: {e}")
    # fallback модели по одной
    fb_key = os.getenv("FALLBACK_API_KEY", "")
    for m in [x.strip() for x in (fb_models or "").split(",") if x.strip()]:
        t = time.time()
        try:
            r = await ai._call_provider(fb_base, fb_key, m, msgs, 0.2, 64, 40.0)
            ck(f"fallback {m}", bool(r and r.strip()), f"{time.time()-t:.1f}s → {r!r}")
        except Exception as e:
            ck(f"fallback {m}", False, f"EXC {type(e).__name__}: {e}")

    # ── 2. Реальное переключение: ломаем primary → должен уйти в fallback ──
    print("\n─── форсированный фоллбэк (primary заведомо сломан) ───")
    ai_broken = AIAssistant()
    ai_broken.base_url = "http://127.0.0.1:59999"  # никто не слушает → primary падает
    t = time.time()
    r = await ai_broken._call_api(msgs, temperature=0.2, max_tokens=64, timeout=45.0)
    ck("fallback подхватывает при мёртвом primary", bool(r and r.strip()), f"{time.time()-t:.1f}s → {r!r}")

    # ── 3. Сквозные AI-функции (то, что реально дергают бот и сайт) ──
    print("\n─── сквозные AI-функции ───")
    profile = {"specialty": "Python разработчик", "skills": "Python, Django, PostgreSQL",
               "city": "Москва", "experience": "3 года"}
    vac = {"title": "Backend-разработчик Python", "company": "ООО Ромашка",
           "description": "Django, REST, PostgreSQL, Docker. Удалёнка.",
           "salary": "от 250000", "location": "Москва"}
    # 3a cover letter
    t = time.time()
    try:
        cl = await ai.generate_cover_letter(profile, vac, "", "profile")
        txt = cl.get("generated_text", "") if isinstance(cl, dict) else str(cl or "")
        ck("generate_cover_letter (бот+сайт)", len(txt) > 80, f"{time.time()-t:.1f}s, {len(txt)} симв")
    except Exception as e:
        ck("generate_cover_letter", False, f"EXC {e}")
    # 3b parse_user_description (онбординг)
    t = time.time()
    try:
        pr = await ai.parse_user_description("ищу удалённую работу python разработчиком в москве от 200к")
        ck("parse_user_description (онбординг)", bool(pr and pr.get("specialty")), f"{time.time()-t:.1f}s → {pr}")
    except Exception as e:
        ck("parse_user_description", False, f"EXC {e}")
    # 3c answer_career_question (коуч бот+сайт)
    t = time.time()
    try:
        ans = await ai.answer_career_question({"question": "Как повысить шансы на оффер?",
                                               "user_profile": profile, "vacancy": vac})
        ck("answer_career_question (коуч)", bool(ans and len(str(ans)) > 40), f"{time.time()-t:.1f}s, {len(str(ans or ''))} симв")
    except Exception as e:
        ck("answer_career_question", False, f"EXC {e}")
    # 3d score_vacancy_match
    t = time.time()
    try:
        sc = await ai.score_vacancy_match(profile, vac)
        ck("score_vacancy_match (% совпадения)", isinstance(sc, dict) and "score" in sc, f"{time.time()-t:.1f}s → {sc}")
    except Exception as e:
        ck("score_vacancy_match", False, f"EXC {e}")

    print("\n" + "=" * 60)
    print(f"ИТОГ ИИ: {len(PASS)} PASS / {len(FAIL)} FAIL")
    for f in FAIL:
        print("  ❌", f)
    print("=" * 60)

asyncio.run(main())
