#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Erzeugt aus dem RPRO3-Dedup (compare_rpro3.dedup) Rückfrage-Tickets für die Züchterin:
mehrdeutige Namen mit >=2 informativen Varianten (echte „gleich/verschieden?"-Entscheidungen).

Pro Variante wird die HERKUNFT hinterlegt (RennmausPro-Datensatz-Nr., eigenes Tier vs. externer
Ahn, Züchter/Herkunft). Wo ein passendes BESTEHENDES Tier im aktuellen Bestand gefunden wird,
kommt ein Hyperlink in die Frage ([Name ansehen](/rennmaeuse/<id>)), den die Tickets-UI klickbar
rendert. Das Ticket bekommt zusätzlich GerbilId (für den „Datensatz ansehen"-Link in der Kopfzeile)
und ein internes AgentContext (Varianten + rids + gefundene Tier-IDs) für den späteren Importer.

Postet NICHTS — schreibt nur die Kandidaten-JSON. Das Posten macht rpro3_post_tickets.py.

Aufruf:  python rpro3_tickets.py <_rpro3.db> <scratch-dir mit cur_gerbils.json> [out.json]
"""
from __future__ import annotations
import sys, json, re, datetime
import compare_rpro3 as C

LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
SUFFIX_RE = re.compile(r"\s+(von den |von der |von dem |vom |von |of |gen\.\s|v\.\s|de\s|du\s)", re.IGNORECASE)

def informative(v):
    return bool(v["dob"] or v["farbe"] or v["origin"])

def strip_suffix(name):
    """Zucht-Suffix abtrennen (z. B. „Blacky von den Kleinen Chaoten" -> „blacky")."""
    n = name or ""
    m = SUFFIX_RE.search(n)
    if m:
        n = n[:m.start()]
    return C.norm_name(n)

def parse_dob(s):
    if not s:
        return None
    try:
        return datetime.date.fromisoformat(str(s)[:10])
    except ValueError:
        return None

def build_current_index(scratch):
    g = json.load(open(f"{scratch}\\cur_gerbils.json", encoding="utf-8"))
    g = g["items"] if isinstance(g, dict) else g
    idx_full, idx_strip = {}, {}
    for x in g:
        rec = {"id": x["id"], "name": x["name"], "dob": parse_dob(x.get("dateOfBirth"))}
        idx_full.setdefault(C.norm_name(x["name"]), []).append(rec)
        idx_strip.setdefault(strip_suffix(x["name"]), []).append(rec)
    return idx_full, idx_strip

def match_current(name, dob, idx_full, idx_strip):
    """Eindeutiges bestehendes Tier zu (Name, DOB) finden — sonst None (keine falschen Links)."""
    key = C.norm_name(name)
    cands = idx_full.get(key) or idx_strip.get(strip_suffix(name)) or []
    if not cands:
        return None
    if dob:
        near = [c for c in cands if c["dob"] and abs((c["dob"] - dob).days) <= 31]
        if len(near) == 1:
            return near[0]
        if near:
            return None  # mehrdeutig -> nicht verlinken
    if len(cands) == 1:
        return cands[0]
    return None  # mehrdeutig -> nicht verlinken

def source_label(v):
    rid = v["rids"][0] if v["rids"] else "?"
    if v["is_own"]:
        return f"eigenes Tier (RennmausPro-Nr. {rid})"
    return f"externer Ahn (RennmausPro-Nr. {rid})"

def fmt_variant(letter, v, match):
    dob = ", ".join(v["dob"]) or "unbekannt"
    farbe = ", ".join(v["farbe"]) or "unbekannt"
    orig = ", ".join(v["origin"]) or "unbekannt"
    cnt = f", {v['n']}× im Import" if v["n"] > 1 else ""
    link = f" — [Tier ansehen](/rennmaeuse/{match['id']})" if match else ""
    return (f"• **{letter}**: {source_label(v)} — geboren {dob}, Farbe {farbe}, "
            f"Herkunft {orig}{cnt}{link}")

def build_question(name, rows):
    lines = [
        f"Beim Import aus RennmausPro gibt es mehrere Tiere mit dem Namen „{name}\". "
        "Manchmal hat RennmausPro dasselbe Tier mehrfach gespeichert, manchmal sind es "
        "wirklich verschiedene Tiere mit zufällig gleichem Namen.",
        "",
        "Welche davon sind **dasselbe Tier**, welche sind **verschiedene**? "
        "Die Herkunft jeder Variante steht dabei:",
        "",
    ]
    for letter, v, match in rows:
        lines.append(fmt_variant(letter, v, match))
    lines += [
        "",
        "Antworte am einfachsten mit den Buchstaben, z. B.: "
        "„A und B sind dasselbe Tier, C ist ein anderes\" · „alle dasselbe\" · „alle verschieden\".",
    ]
    return "\n".join(lines)

def main():
    db = sys.argv[1]
    scratch = sys.argv[2]
    out = sys.argv[3] if len(sys.argv) > 3 else None

    R = C.load_rpro3(db)
    _, ambiguous, _ = C.dedup(R["animals"])
    idx_full, idx_strip = build_current_index(scratch)

    tickets = []
    for name, variants in ambiguous:
        info = [v for v in variants if informative(v)]
        if len(info) < 2:
            continue
        info.sort(key=lambda v: (not v["is_own"], -v["n"]))

        rows, matches = [], []
        for i, v in enumerate(info):
            dob = parse_dob(v["dob"][0]) if v["dob"] else None
            m = match_current(name, dob, idx_full, idx_strip)
            rows.append((LETTERS[i], v, m))
            matches.append(m)

        # Ticket-GerbilId: bevorzugt das gematchte eigene Tier, sonst erster Treffer.
        primary = next((m for (l, v, m) in rows if v["is_own"] and m), None) or next((m for m in matches if m), None)

        agent_ctx = {
            "source": "rpro3-ambiguity",
            "name": name,
            "variants": [
                {"label": LETTERS[i], "rids": v["rids"], "count": v["n"],
                 "dob": v["dob"], "farbe": v["farbe"], "origin": v["origin"],
                 "is_own": v["is_own"], "matched_gerbil_id": (matches[i]["id"] if matches[i] else None)}
                for i, v in enumerate(info)
            ],
        }
        tickets.append({
            "Message": f"RennmausPro-Import: Name „{name}\" kommt mehrfach vor "
                       f"({len(info)} Varianten) — dasselbe Tier oder verschiedene?",
            "Context": "rpro3-import",
            "EntityName": name,
            "GerbilId": primary["id"] if primary else None,
            "Question": build_question(name, rows),
            "AgentContext": json.dumps(agent_ctx, ensure_ascii=False),
            "_own": any(v["is_own"] for v in info),
            "_nvars": len(info),
            "_linked": sum(1 for m in matches if m),
        })

    tickets.sort(key=lambda t: (not t["_own"], -t["_nvars"]))
    linked = sum(t["_linked"] for t in tickets)
    print(f"Ticket-Kandidaten: {len(tickets)}  (eigenes Tier beteiligt: {sum(1 for t in tickets if t['_own'])})")
    print(f"Varianten mit Tier-Hyperlink: {linked}")
    print(f"Tickets mit GerbilId (Kopf-Link): {sum(1 for t in tickets if t['GerbilId'])}")
    if out:
        json.dump(tickets, open(out, "w", encoding="utf-8"), ensure_ascii=False, indent=2)
        print(f"geschrieben: {out}")

if __name__ == "__main__":
    main()
