"""
regression_corpus_check.py
==========================
Regression checker untuk R2-11 (cross-domain false-positive guard).

Tujuan:
- Memastikan paper domain perikanan (contoh: lele/Clarias) tidak terhubung
  dengan paper domain AI/RAG/vector melalui edge SIMILAR_*.

Cara menjalankan:
  python regression_corpus_check.py
"""

import os
import sys
from dotenv import load_dotenv
from neo4j import GraphDatabase


load_dotenv()

NEO4J_URI = os.getenv("NEO4J_URI", "")
NEO4J_USERNAME = os.getenv("NEO4J_USERNAME", "neo4j")
NEO4J_PASSWORD = os.getenv("NEO4J_PASSWORD", "")

FISHERY_KEYWORDS = ["lele", "clarias", "budidaya ikan", "kolam terpal", "perikanan"]
AI_KEYWORDS = [
    "ragas",
    "vector",
    "embedding",
    "retrieval augmented",
    "semantic",
    "graph",
]


def main() -> int:
    if not all([NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD]):
        print("❌ ERROR: Kredensial Neo4j belum lengkap di file .env")
        return 1

    driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USERNAME, NEO4J_PASSWORD))

    # Param names harus unik per grup untuk menghindari overwrite.
    params = {}
    for i, kw in enumerate(FISHERY_KEYWORDS):
        params[f"kw_a_{i}"] = kw
        params[f"kw_b_{i}"] = kw
    for i, kw in enumerate(AI_KEYWORDS):
        params[f"kw_ai_a_{i}"] = kw
        params[f"kw_ai_b_{i}"] = kw

    fish_a = "(" + " OR ".join(
        [f"toLower(a.title) CONTAINS toLower($kw_a_{i})" for i in range(len(FISHERY_KEYWORDS))]
    ) + ")"
    fish_b = "(" + " OR ".join(
        [f"toLower(b.title) CONTAINS toLower($kw_b_{i})" for i in range(len(FISHERY_KEYWORDS))]
    ) + ")"
    ai_a = "(" + " OR ".join(
        [f"toLower(a.title) CONTAINS toLower($kw_ai_a_{i})" for i in range(len(AI_KEYWORDS))]
    ) + ")"
    ai_b = "(" + " OR ".join(
        [f"toLower(b.title) CONTAINS toLower($kw_ai_b_{i})" for i in range(len(AI_KEYWORDS))]
    ) + ")"

    corpus_query = f"""
    MATCH (n:Literature)
    RETURN
      sum(CASE WHEN {fish_a.replace('a.', 'n.')} THEN 1 ELSE 0 END) AS fishery_nodes,
      sum(CASE WHEN {ai_a.replace('a.', 'n.')} THEN 1 ELSE 0 END) AS ai_nodes,
      count(n) AS total_nodes
    """

    cross_domain_edge_query = f"""
    MATCH (a:Literature)-[r]-(b:Literature)
    WHERE type(r) STARTS WITH 'SIMILAR_'
      AND (
        ({fish_a} AND {ai_b})
        OR
        ({ai_a} AND {fish_b})
      )
      AND elementId(a) < elementId(b)
    RETURN
      a.title AS source_title,
      b.title AS target_title,
      type(r) AS rel_type,
      r.score AS score,
      coalesce(r.reasoning, r.summary, '') AS reasoning
    ORDER BY score DESC
    """

    with driver.session() as session:
        corpus_info = session.run(corpus_query, params).single()
        records = list(session.run(cross_domain_edge_query, params))

    driver.close()

    total_nodes = corpus_info["total_nodes"] if corpus_info else 0
    fishery_nodes = corpus_info["fishery_nodes"] if corpus_info else 0
    ai_nodes = corpus_info["ai_nodes"] if corpus_info else 0

    print("=" * 72)
    print("R2-11 Regression Corpus Check")
    print("=" * 72)
    print(f"Total node corpus          : {total_nodes}")
    print(f"Node domain perikanan      : {fishery_nodes}")
    print(f"Node domain AI/vector      : {ai_nodes}")
    print(f"Cross-domain edge terdeteksi: {len(records)}")

    if records:
        print("\n❌ FAIL: Ditemukan edge lintas domain yang seharusnya tidak relevan.")
        for idx, rec in enumerate(records, 1):
            print(
                f"  [{idx}] {rec['rel_type']} | score={rec['score']:.4f}\n"
                f"       {rec['source_title']}\n"
                f"       {rec['target_title']}"
            )
        return 2

    if fishery_nodes == 0 or ai_nodes == 0:
        print("\n⚠️  WARNING: Salah satu domain corpus belum terdeteksi, hasil check kurang kuat.")
        return 0

    print("\n✅ PASS: Tidak ada edge lintas domain perikanan vs AI/vector pada graf saat ini.")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
