#!/usr/bin/env python3
"""
Validate configuration files for data quality validation deployment.

This script validates:
1. YAML configuration files (settings.yaml and view configs)
2. SHACL rules file syntax (TTL format)
3. Required fields and references

Usage:
    python scripts/validate_config.py [--shacl-only] [--config-only]
"""

import argparse
import os
import sys
from pathlib import Path

from shared import get_repo_root, load_settings, load_view_configs


def validate_yaml_configs(repo_root: Path, config_env: str, settings: dict, view_configs: list[dict]) -> list[str]:
    """
    Validate YAML configuration files.

    Returns a list of error messages (empty if valid).
    """
    errors = []

    # Get settings file directory (paths in settings are relative to this directory)
    settings_dir = repo_root / "config" / "environments" / config_env

    # Validate settings.yaml (already loaded)
    try:
        # function is optional - defaults are set in DeploymentSettings.model_post_init
        required = ["workflow", "trigger", "records", "datamodel", "shacl_rules"]
        for key in required:
            if key not in settings:
                errors.append(f"Missing required key in settings.yaml: {key}")

        if "shacl_rules" in settings and "source_dir" in settings["shacl_rules"]:
            shacl_dir = settings_dir / settings["shacl_rules"]["source_dir"]
            if not shacl_dir.exists():
                errors.append(
                    f"SHACL rules directory not found: {shacl_dir} (from settings: {settings['shacl_rules']['source_dir']})"
                )
        print("[OK] config/settings.yaml")
    except Exception as e:
        errors.append(f"Error parsing settings.yaml: {e}")

    # Validate view configs (already loaded)
    if not view_configs:
        errors.append("No view configuration files found for selected CONFIG_ENV")
        return errors

    for config in view_configs:
        filename = config.get("_filename", "unknown")
        try:
            # Check required keys
            required = ["view", "instance_space", "shacl_rules", "validation", "records"]
            for key in required:
                if key not in config:
                    errors.append(f"Missing required key in {filename}: {key}")

            # Check SHACL rules file exists
            if "shacl_rules" in config and "file" in config["shacl_rules"]:
                shacl_dir = settings_dir / settings.get("shacl_rules", {}).get("source_dir", "shacl_rules")
                shacl_path = shacl_dir / config["shacl_rules"]["file"]
                if not shacl_path.exists():
                    errors.append(f"SHACL rules file not found: {shacl_path}")

            # Check view has required subkeys
            if "view" in config:
                for subkey in ["space", "external_id", "version"]:
                    if subkey not in config["view"]:
                        errors.append(f"Missing view.{subkey} in {filename}")

            # Check records has required subkeys
            if "records" in config:
                for subkey in ["rule_set_id", "rule_set_version"]:
                    if subkey not in config["records"]:
                        errors.append(f"Missing records.{subkey} in {filename}")

            print(f"[OK] {filename}")

        except Exception as e:
            errors.append(f"Error parsing {filename}: {e}")

    return errors


def validate_shacl_syntax(repo_root: Path, config_env: str, settings: dict) -> list[str]:
    """
    Validate SHACL rules file syntax (TTL format).

    Returns a list of error messages (empty if valid).
    """
    try:
        from rdflib import Graph
    except ImportError:
        print("[SKIP] rdflib not installed, skipping SHACL syntax validation")
        return []

    errors = []

    # Get settings file directory (paths in settings are relative to this directory)
    settings_dir = repo_root / "config" / "environments" / config_env

    # Get shacl_rules source_dir from settings (relative to settings file directory)
    shacl_dir = settings_dir / settings.get("shacl_rules", {}).get("source_dir", "shacl_rules")

    if not shacl_dir.exists():
        errors.append(f"SHACL rules directory not found: {shacl_dir}")
        return errors

    ttl_files = list(shacl_dir.glob("*.ttl"))
    if not ttl_files:
        errors.append(f"No TTL files found in {shacl_dir}")
        return errors

    for ttl_file in ttl_files:
        try:
            g = Graph()
            g.parse(ttl_file, format="turtle")
            print(f"[OK] {ttl_file.name} ({len(g)} triples)")
        except Exception as e:
            errors.append(f"{ttl_file.name}: {e}")

    return errors


def main():
    parser = argparse.ArgumentParser(description="Validate configuration files for data quality validation")
    parser.add_argument("--shacl-only", action="store_true", help="Only validate SHACL syntax")
    parser.add_argument("--config-only", action="store_true", help="Only validate YAML configs")
    args = parser.parse_args()

    # Determine repo root
    repo_root = get_repo_root()
    config_env = os.environ.get("CONFIG_ENV")

    all_errors = []
    settings = load_settings(repo_root, config_env)
    view_configs = load_view_configs(repo_root, config_env)

    # Validate YAML configs
    if not args.shacl_only:
        print("Validating YAML configuration files...")
        print("-" * 40)
        yaml_errors = validate_yaml_configs(repo_root, config_env, settings, view_configs)
        all_errors.extend(yaml_errors)
        print()

    # Validate SHACL syntax
    if not args.config_only:
        print("Validating SHACL rules syntax...")
        print("-" * 40)
        shacl_errors = validate_shacl_syntax(repo_root, config_env, settings)
        all_errors.extend(shacl_errors)
        print()

    # Report results
    if all_errors:
        print("=" * 40)
        print("VALIDATION FAILED")
        print("=" * 40)
        print(f"\n{len(all_errors)} error(s) found:\n")
        for error in all_errors:
            print(f"  - {error}")
        return 1
    else:
        print("=" * 40)
        print("VALIDATION PASSED")
        print("=" * 40)
        print("\nAll configuration files are valid!")
        return 0


if __name__ == "__main__":
    sys.exit(main())
