from __future__ import annotations

import argparse
import json
from typing import Any

from app.core.common.identifiers import new_governance_uid


GOVERNANCE_LABELS = ("BusinessDomain", "DataMeta", "DataFlow", "DataSource")


def ensure_uid_constraints(session: Any) -> None:
    constraints = {
        "BusinessDomain": "business_domain_uid",
        "DataMeta": "data_meta_uid",
        "DataFlow": "data_flow_uid",
        "DataSource": "datasource_uid",
    }
    for label, constraint in constraints.items():
        session.run(
            f"CREATE CONSTRAINT {constraint} IF NOT EXISTS "
            f"FOR (n:{label}) REQUIRE n.uid IS UNIQUE"
        )


def report_missing_uids(session: Any, limit: int = 100) -> dict[str, list[dict[str, Any]]]:
    report: dict[str, list[dict[str, Any]]] = {}
    for label in GOVERNANCE_LABELS:
        result = session.run(
            f"MATCH (n:{label}) WHERE n.uid IS NULL "
            "RETURN elementId(n) AS legacy_id, n.name_zh AS name_zh "
            "ORDER BY legacy_id LIMIT $limit",
            {"limit": int(limit)},
        )
        report[label] = [dict(record) for record in result]
    return report


def backfill_missing_uids(session: Any, limit: int = 100) -> dict[str, int]:
    report = report_missing_uids(session, limit=limit)
    counts: dict[str, int] = {}
    for label, records in report.items():
        counts[label] = 0
        for record in records:
            session.run(
                f"MATCH (n:{label}) WHERE elementId(n) = $legacy_id AND n.uid IS NULL "
                "SET n.uid = $uid",
                {
                    "legacy_id": str(record["legacy_id"]),
                    "uid": new_governance_uid(),
                },
            )
            counts[label] += 1
    return counts


def main() -> None:
    parser = argparse.ArgumentParser(description="Audit stable governance UIDs")
    parser.add_argument("--limit", type=int, default=100)
    parser.add_argument("--backfill", action="store_true")
    parser.add_argument("--ensure-constraints", action="store_true")
    args = parser.parse_args()

    from app.services.neo4j_driver import neo4j_driver

    with neo4j_driver.get_session() as session:
        report = report_missing_uids(session, limit=args.limit)
        print(json.dumps(report, ensure_ascii=False, indent=2))
        if args.backfill:
            counts = backfill_missing_uids(session, limit=args.limit)
            print(json.dumps({"backfilled": counts}, ensure_ascii=False))
        if args.ensure_constraints:
            ensure_uid_constraints(session)


if __name__ == "__main__":
    main()
