"""
Contrasta dos fuentes de tags sobre las MISMAS imagenes:
  - Danbooru  : los tags que puso la comunidad + su 'rating' (g/s/q/e)
  - WD14      : lo que devuelve nuestro tagger

Responde a tres preguntas:
  1. ¿El rating de Danbooru coincide con NUESTRA severidad por tags?
     (donde no, nuestra clasificacion de severidad se equivoca)
  2. ¿Cuantos tags de WD14 existen en el vocabulario de Danbooru?
     (cuanto menor, peor es nuestro tagger)
  3. ¿Que tags pone WD14 que Danbooru no tiene, y al reves?

    python Engine/comparar_danbooru.py
    python Engine/comparar_danbooru.py --verbose
"""
import argparse
import json
import re
import sys
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(Path(__file__).resolve().parent))

DAN_DIR = BASE_DIR / "Archivos" / "wd14" / "danbooru"
WD_DIR = BASE_DIR / "Archivos" / "wd14" / "tags_danbooru"
IMG_EXT = (".jpg", ".jpeg", ".png", ".webp", ".bmp")

# nuestra severidad, la misma logica que wd14_blocks.severity()
SEV_EXPLICIT = (
    "sex", "vaginal", "penetration", "anal", "anal_sex", "creampie",
    "fellatio", "blowjob", "paizuri", "titjob", "handjob", "footjob",
    "cum_in_mouth", "cum_in_pussy", "cum_in_vagina", "cum_overflow",
    "ejaculation", "cumshot", "deepthroat", "after_sex", "netorare",
    "group_sex", "threesome", "standing_sex", "cowgirl_position",
    "reverse_cowgirl_position", "missionary", "doggystyle", "doggy",
    "69_position", "sex_from_behind", "spread_legs", "pov_crotch",
)
SEV_SEXUAL = (
    "penis", "pussy", "anus", "nipples", "testicles", "clitoris", "erection",
    "uncensored", "topless", "bottomless", "ahegao", "spread_ass", "ass_focus",
    "pussy_peek", "between_breasts", "sideboob", "underboob", "pussy_juice",
    "cum", "covered_nipples", "cum_on_body", "cum_on_breasts",
    "internal_cumshot", "cross-section",
)
SEV_NUDITY = ("nude", "completely_nude", "partially_nude", "undressed")

RATING_NOS = {"g": "sfw", "s": "spicy", "q": "spicy", "e": "explicit"}


def nuestra_severidad(tags):
    s = {t.lower() for t in tags}
    if s & set(SEV_EXPLICIT):
        return "explicit"
    if s & set(SEV_SEXUAL):
        return "spicy"
    if s & set(SEV_NUDITY):
        return "spicy"
    return "sfw"


def norm(t):
    """Danbooru usa espacios, nosotros guiones bajos."""
    return t.lower().strip().replace(" ", "_")


def main():
    ap = argparse.ArgumentParser(description="Compara Danbooru vs WD14")
    ap.add_argument("--verbose", action="store_true", help="detalle por imagen")
    args = ap.parse_args()

    man_path = sorted(DAN_DIR.glob("danbooru_manifest_*.json"))[-1]
    manifest = json.loads(man_path.read_text(encoding="utf-8-sig"))
    by_file = {m["archivo"]: m for m in manifest}

    filas = []
    for img in sorted(by_file):
        stem = Path(img).stem
        wd_file = WD_DIR / (stem + ".txt")
        if not wd_file.exists():
            continue
        dan = [norm(t) for t in (by_file[img].get("danbooru_tags") or [])]
        wd = [norm(t) for t in wd_file.read_text(encoding="utf-8").split(",")
              if t.strip()]
        filas.append((img, by_file[img], set(dan), set(wd)))

    if not filas:
        raise SystemExit("[!] No hay .txt de WD14. Corre antes wd14_tagger.py")

    print("=" * 76)
    print("1) NUESTRA SEVERIDAD  vs  EL RATING DE DANBOORU")
    print("=" * 76)
    print("   imagen                            danbooru  nuestra  ?")
    aciertos = 0
    for img, m, dan, wd in filas:
        r = m["rating"]
        nuestra = nuestra_severidad(wd)
        esperado = RATING_NOS.get(r, "?")
        ok = nuestra == esperado
        aciertos += ok
        print("   %-34s %-9s %-9s %s" % (Path(img).name[:34], r,
                                          nuestra, "OK" if ok else "DIFIERE"))
    print("\n   coinciden: %d/%d" % (aciertos, len(filas)))

    print("\n" + "=" * 76)
    print("2) VOCABULARIO: ¿los tags de WD14 existen en Danbooru?")
    print("=" * 76)
    vocab = set()
    for _i, _m, dan, _wd in filas:
        vocab |= dan
    tot = ok_t = 0
    inventados = {}
    for _i, _m, _dan, wd in filas:
        for t in wd:
            tot += 1
            if t in vocab:
                ok_t += 1
            else:
                inventados[t] = inventados.get(t, 0) + 1
    pct = ok_t / tot * 100 if tot else 0
    print("   tags WD14 totales      : %d" % tot)
    print("   presentes en Danbooru  : %d  (%.1f%%)" % (ok_t, pct))
    print("   no encontrados         : %d" % (tot - ok_t))
    if inventados:
        top = sorted(inventados.items(), key=lambda x: -x[1])[:20]
        print("\n   mas repetidos que no estan en Danbooru:")
        for t, n in top:
            print("      %2dx  %s" % (n, t))

    print("\n" + "=" * 76)
    print("3) SOLAPAMIENTO POR IMAGEN")
    print("=" * 76)
    print("   imagen                            WD14  coinc.  solo_WD14  solo_DAN")
    for img, _m, dan, wd in filas:
        c = len(wd & dan)
        print("   %-34s %4d  %6d  %10d  %9d" % (
            Path(img).name[:34], len(wd), c, len(wd - dan), len(dan - wd)))

    if args.verbose:
        print("\n" + "=" * 76)
        print("DETALLE")
        print("=" * 76)
        for img, _m, dan, wd in filas:
            print("\n--- %s" % img)
            print("  solo WD14 : %s" % ", ".join(sorted(wd - dan)[:30]))
            print("  solo DAN  : %s" % ", ".join(sorted(dan - wd)[:30]))


if __name__ == "__main__":
    main()