"""Egzersiz/doğaçlama kısmı için saniyelik kamera incelemesi (WSL, görüntülü Qwen). Her saniye iki kameranın karesi,
o anın konuşması ve sırası gelen kişi verilir; model sırası gelen kişinin her kamerada ne kadar göründüğünü söyler.
Çıktı: vlm_egzersiz.jsonl. Kaldığı yerden devam eder."""
import base64, bisect, glob, json, os, re, 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"))
OUT = f"{K}/vlm_egzersiz.jsonl"
A0, A1 = 75999, 77692
TEORI = [(71223, 73481), (74726, 75999)]
# (başlangıç, kim, ne) — transkriptten
SIRA = [(75999, "herkes", "beden tarama egzersizi: herkes ayakta, gözler kapalı, hoca yönetiyor"),
        (76270, "İlhan (oturuyor) ve hoca", "doğaçlama nedir sohbeti"),
        (76340, "İlhan", "sahnede: su içen zürafa, sonra çatıda mahsur kalmış kedi"),
        (76450, "sahneye çıkan katılımcı", "duruş çalışması: hoca duruşunu düzeltiyor"),
        (76740, "aynı katılımcı", "sahnede: ayran dolu sürahi, sonra karnı aç balık"),
        (76850, "hoca ve sıradaki katılımcı (İlhan)", "geçiş, hoca duruş anlatıyor"),
        (76920, "İlhan", "sahnede: aşık Çizmeli Kedi"),
        (77060, "bir katılımcı", "sahnede: zararsız yılan, sonra aç tavşan"),
        (77190, "İbrahim", "sahnede: haberci güvercin"),
        (77290, "Enes", "sahnede: overthinking yapan maymun"),
        (77390, "Furkan", "sahnede: ayağına çivi batmış horoz"),
        (77520, "hoca", "kapanış konuşması, gelecek haftalar")]

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]; i = bisect.bisect_left(v, (t,))
    c = [x for x in v[max(i - 1, 0):i + 1] if abs(x[0] - t) <= 0.7]
    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 + 3:
            kim = "HOCA" if x["konusmaci"] == "EĞİTMEN" else "KATILIMCI"
            if kim != spk: s += f"\n{kim}: "; spk = kim
            s += x["kelime"] + " "
    return s.strip() or "(konuşma yok — pantomim olabilir)"


ISTEM = """Oyunculuk atölyesinin doğaçlama bölümü, iki kamera. Kurgu için kamera seçiyoruz.
HOCA: sakallı, gözlüklü, koyu gri kapüşonlu, bej pantolon. Arka planda lacivert pano, sarı "DADI" logosu.
Şu an sırası olan: {kim} — {ne}.
Bu anın konuşması: {baglam}

Her kamera için SIRASI OLAN KİŞİYE bak (hoca değil, o an oynayan/konuşan kişi). SADECE tek satır JSON:
{{"A":{{"g":"tam|cogu|az|yok","y":0|1,"h":0|1,"p":0-10}},"B":{{...}},"t":"A|B"}}
g = sırası olan kişi kadrajda ne kadar görünüyor (tam: tüm vücut/yapılan hareket okunuyor; cogu: büyük kısmı; az: sadece bir parçası, kenarda, eğilmiş/kesilmiş; yok: görünmüyor)
y = yüzü görünüyor; h = kamera hareketli/sallantılı/bulanık; p = bu kamera bu an için ne kadar iyi (0-10); t = tercih.
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 None                        # kare yok: kaydetme, sonra tekrar denenir
    if t >= A0:
        s = [x for x in SIRA if x[0] <= t][-1]
    else:                                                  # teori: konuşan transkriptten
        ks = [x for x in W if t - 1.5 <= x["saat"] <= t + 1.5]
        hoca = sum(x["konusmaci"] == "EĞİTMEN" for x in ks)
        s = (0, "hoca", "ders anlatıyor") if not ks or hoca >= len(ks) / 2 else \
            (0, "hoca", "bir katılımcı (kadrajda değil) konuşuyor; hocayı dinlerken/tepki verirken göster, mümkünse geniş açı")
    icerik = [{"type": "text", "text": ISTEM.format(kim=s[1], ne=s[2], baglam=baglam(t))}]
    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)}}]
    istek = {"model": "bot-llm", "temperature": 0.1, "max_tokens": 80, "chat_template_kwargs": {"enable_thinking": False},
             "messages": [{"role": "user", "content": icerik}]}
    for _ 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"]
            j = json.loads(re.search(r"\{.*\}", c, re.S).group(0)); j["t_"] = j.pop("t", None); j["t"] = t; j["kim"] = s[1]
            return j
        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 t in range(A0, A1) if float(t) not in bitti] + \
        [float(t) for a, b in TEORI for t in range(a, b, 2) if float(t) not in bitti]
print(len(anlar), "an", flush=True)
with open(OUT, "a") as f, ThreadPoolExecutor(3) as ex:
    for i, r in enumerate(ex.map(sor, anlar)):
        if r is not None: f.write(json.dumps(r, ensure_ascii=False) + "\n"); f.flush()
        if i % 100 == 0: print(i, flush=True)
print("BİTTİ", flush=True)
