"""
Discover RAW tables that feed the RMDM model via CDF Transformations.

Connects to abp-dev, lists all transformations targeting RMDM/Valhall instance spaces,
parses their SQL queries for RAW table references, and samples each table for schema info.
"""

import re
import sys
from collections import defaultdict
from pathlib import Path

# Add repo root to path so we can import cognite_data_quality
sys.path.insert(0, str(Path(__file__).parent.parent))

from cognite_data_quality import load_cognite_client_from_toml

TOML_PATH = Path(__file__).parent.parent / "config/environments/abp-dev/abp-dev.toml"

# Spaces that indicate RMDM destination
RMDM_SPACES = {
    "sp_valhall",
    "sp_rmdm_dm",
    "sp_yggdrasil-twin-commissioning-types",
}

RAW_PATTERN = re.compile(
    r"`_cdf\.raw`\.`([^`]+)`\.`([^`]+)`",
    re.IGNORECASE,
)
# Alternate pattern without backticks: _cdf.raw.db.table
RAW_PATTERN_PLAIN = re.compile(
    r"\b_cdf\.raw\.([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)\b",
    re.IGNORECASE,
)


def extract_raw_tables(sql: str) -> list[tuple[str, str]]:
    results = RAW_PATTERN.findall(sql)
    results += RAW_PATTERN_PLAIN.findall(sql)
    return list(dict.fromkeys(results))  # deduplicate, preserve order


def destination_label(dest) -> str:
    if dest is None:
        return "unknown"
    dtype = getattr(dest, "type", None) or type(dest).__name__
    view = getattr(dest, "view", None)
    instance_space = getattr(dest, "instance_space", None)
    if view:
        v = view
        ext = getattr(v, "external_id", None) or getattr(v, "externalId", None) or "<unknown_view_external_id>"
        ver = getattr(v, "version", None)
        space = getattr(v, "space", None)
        return f"{dtype}: {space}/{ext} v{ver} (instances in {instance_space})"
    if instance_space:
        return f"{dtype}: instances → {instance_space}"
    return str(dest)


def is_rmdm_destination(dest) -> bool:
    if dest is None:
        return False
    instance_space = getattr(dest, "instance_space", None)
    if instance_space in RMDM_SPACES:
        return True
    # Also check view space
    view = getattr(dest, "view", None)
    if view:
        space = getattr(view, "space", None)
        if space in RMDM_SPACES:
            return True
    return False


def main():
    print(f"Connecting to abp-dev via {TOML_PATH} ...")
    client = load_cognite_client_from_toml(str(TOML_PATH))
    print(f"Connected: project={client.config.project}\n")

    print("Listing all transformations ...")
    transformations = client.transformations.list(limit=-1)
    print(f"Total transformations: {len(transformations)}\n")

    # Filter to RMDM destinations
    rmdm_transforms = [t for t in transformations if is_rmdm_destination(t.destination)]
    print(f"Transformations targeting RMDM/Valhall spaces: {len(rmdm_transforms)}\n")

    # Parse RAW sources
    # raw_table -> list of (transformation_external_id, destination_label)
    raw_to_transforms: dict[tuple[str, str], list[str]] = defaultdict(list)
    transforms_without_raw = []

    for t in rmdm_transforms:
        sql = t.query or ""
        raw_tables = extract_raw_tables(sql)
        dest = destination_label(t.destination)
        if raw_tables:
            for db, table in raw_tables:
                raw_to_transforms[(db, table)].append(f"{t.external_id}  →  {dest}")
        else:
            transforms_without_raw.append(f"{t.external_id}  →  {dest}")

    print("=" * 80)
    print(f"RAW TABLES FEEDING RMDM ({len(raw_to_transforms)} unique tables)")
    print("=" * 80)

    for (db, table), usages in sorted(raw_to_transforms.items()):
        print(f"\n  RAW: {db} / {table}")
        for u in usages:
            print(f"    {u}")

        # Sample the table for row count and schema
        try:
            rows = client.raw.rows.list(db_name=db, table_name=table, limit=5)
            if rows:
                all_cols: set[str] = set()
                for row in rows:
                    if row.columns:
                        all_cols.update(row.columns.keys())
                print(f"    Columns ({len(all_cols)}): {', '.join(sorted(all_cols))}")
            else:
                print("    (table empty or not accessible)")
        except Exception as e:
            print(f"    Could not sample table: {e}")

    print("\n" + "=" * 80)
    print(f"RMDM TRANSFORMATIONS WITH NO RAW SOURCE ({len(transforms_without_raw)})")
    print("=" * 80)
    for t in transforms_without_raw:
        print(f"  {t}")

    print("\nDone.")


if __name__ == "__main__":
    main()
