"""Kamera seçimi için kare incelemesi: WSL'deki görüntülü Qwen (llama-server, bot-llm) her 2 sn'de iki kameranın
karesine ve o anın transkriptine bakıp karar verir. WSL'de çalışır; kaldığı yerden devam eder.
Girdi (aynı klasör): kare/<klip>/<gerçek saat>.jpg, Eğitim_kelimeler.json, klipler.json
Çıktı: vlm.jsonl (her satır bir an)"""
import base64, glob, json, os, re, sys, urllib.request
from concurrent.futures import ThreadPoolExecutor

K = os.path.dirname(os.path.abspath(__file__))
W = json.load(open(f"{K}/Eğitim_kelimeler.json"))
ARALIK = [(71222, 73481), (74726, 77692)]
OUT = f"{K}/vlm.jsonl"

kareler = {"A": [], "B": []}
for d in glob.glob(f"{K}/kare/C*"):
    kam = "A" if os.path.basename(d).startswith("C19") else "B"
    kareler[kam] += [(float(os.path.basename(p)[:-4]), p) for p in glob.glob(f"{d}/*.jpg")]
for v in kareler.values(): v.sort()


def en_yakin(kam, t):
    v = kareler[kam]
    if not v: return None
    import bisect
    i = bisect.bisect_left(v, (t,))
    c = [x for x in v[max(i - 1, 0):i + 1] if abs(x[0] - t) <= 1.2]
    return min(c, key=lambda x: abs(x[0] - t))[1] if c else None


def baglam(t):
    s, spk = "", None
    for x in W:
        if t - 4 <= x["saat"] <= t + 4:
            kim = "HOCA" if x["konusmaci"] == "EĞİTMEN" else "ÖĞRENCİ"
            if kim != spk: s += f"\n{kim}: "; spk = kim
            s += x["kelime"] + " "
    return s.strip() or "(bu anda konuşma yok)"


ISTEM = """Bir oyunculuk atölyesinin iki kameralı çekimi. Kurgu için kamera seçiyoruz.
HOCA: sakallı, gözlüklü, koyu gri kapüşonlu sweatshirt, bej pantolon; arkasında lacivert pano ve sarı "DADI" logosu.
ÖĞRENCİLER: atölyeye katılan gençler (oturuyor ya da sahneye çıkıp doğaçlama/egzersiz yapıyor).
Kamera A: moladan önce sabit, sonra elde (el kamerası). Kamera B: sabit.
Bu anın (±4 sn) konuşması:
{baglam}

Görüntü(ler): {gorseller}
Her kamera için kısa kodlarla değerlendir, SADECE tek satır JSON yaz (açıklama yok):
{{"A":{{"h":0|1,"g":"h|o|ho|k|y","k":0|1,"p":0-10}},"B":{{...}},"t":"A|B|X"}}
h=kamera hareketli/sallantılı/bulanık(1); g=görünen: h=hoca, o=öğrenci, ho=hoca ve öğrenci, k=kalabalık, y=kimse;
k=konuşan veya oynayan kişi görünüyor(1); p=puan 0-10 (konuşan/oynayan net ve iyi kadrajdaysa yüksek; görünmüyorsa, kamera dönüyor/sallanıyor/bulanıksa ya da kimse yoksa düşük);
t=tercih edilen kamera (X=ikisi de kötü). Görüntüsü verilmeyen kamera için null."""


def b64(p): return "data:image/jpeg;base64," + base64.b64encode(open(p, "rb").read()).decode()


def sor(t):
    a, b = en_yakin("A", t), en_yakin("B", t)
    if not a and not b: return dict(t=t, yok=True)
    icerik, ad = [], []
    for kam, p in (("A", a), ("B", b)):
        if p:
            icerik += [{"type": "text", "text": f"Kamera {kam}:"}, {"type": "image_url", "image_url": {"url": b64(p)}}]; ad.append(f"Kamera {kam}")
    icerik.insert(0, {"type": "text", "text": ISTEM.format(baglam=baglam(t), gorseller=", ".join(ad) + " (aşağıda)")})
    istek = {"model": "bot-llm", "temperature": 0.1, "max_tokens": 80, "chat_template_kwargs": {"enable_thinking": False},
             "messages": [{"role": "user", "content": icerik}]}
    for deneme in range(3):
        try:
            r = urllib.request.urlopen(urllib.request.Request("http://127.0.0.1:47841/v1/chat/completions", json.dumps(istek).encode(),
                                                              {"Content-Type": "application/json"}), timeout=300)
            c = json.loads(r.read())["choices"][0]["message"]["content"]
            m = re.search(r"\{.*\}", c, re.S)
            j = json.loads(m.group(0)); G = {"h": "hoca", "o": "ogrenci", "ho": "hoca_ve_ogrenci", "k": "kalabalik", "y": "kimse"}
            out = dict(t=t, tercih={"X": "ikisi_kotu"}.get(j.get("t"), j.get("t")))
            for kam in "AB":
                v = j.get(kam)
                out[kam] = None if not isinstance(v, dict) else {"hareketli_bulanik": bool(v.get("h")), "gorunen": G.get(v.get("g"), v.get("g")),
                                                                 "konusan_veya_oynayan_gorunuyor": bool(v.get("k")), "puan": v.get("p", 5)}
            return out
        except Exception as e:
            hata = str(e)
    return dict(t=t, hata=hata)


bitti = set()
if os.path.exists(OUT):
    for l in open(OUT):
        try: bitti.add(json.loads(l)["t"])
        except Exception: pass
anlar = [float(t) for a, b in ARALIK for t in range(a, b, 2) if float(t) not in bitti]
if len(sys.argv) > 1: anlar = anlar[:int(sys.argv[1])]
print(len(anlar), "an kaldı", flush=True)
with open(OUT, "a") as f, ThreadPoolExecutor(3) as ex:
    for i, r in enumerate(ex.map(sor, anlar)):
        f.write(json.dumps(r, ensure_ascii=False) + "\n"); f.flush()
        if i % 50 == 0: print(i, flush=True)
print("BİTTİ", flush=True)
