"""
Utility functions for DLT Ingestion Framework
"""

import os
import yaml
from typing import Any, Dict, Optional
from pathlib import Path


def deep_merge(base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]:
    """
    Deep merge two dicts, override takes precedence.

    Args:
        base: Base dictionary
        override: Override dictionary (values take precedence)

    Returns:
        Merged dictionary
    """
    result = base.copy()
    for key, value in override.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = deep_merge(result[key], value)
        else:
            result[key] = value
    return result


def load_yaml(file_path: str) -> Dict[str, Any]:
    """
    Load a YAML file and return its contents.

    Args:
        file_path: Path to YAML file

    Returns:
        Dictionary with YAML contents

    Raises:
        FileNotFoundError: If file doesn't exist
        yaml.YAMLError: If YAML is invalid
    """
    with open(file_path, 'r') as f:
        return yaml.safe_load(f) or {}


def load_yaml_from_lakehouse(path: str) -> Dict[str, Any]:
    """
    Load a YAML file from lakehouse path.

    In Fabric notebooks, lakehouse paths like /lakehouse/default/Files/...
    are directly accessible as regular file paths.

    Args:
        path: Lakehouse path (e.g., /lakehouse/default/Files/configs/...)

    Returns:
        Dictionary with YAML contents
    """
    return load_yaml(path)


def get_base_path() -> str:
    """
    Get the base path for the DLT ingestion framework.

    Returns:
        Base path in lakehouse
    """
    return os.environ.get(
        "DLT_INGESTION_BASE_PATH",
        "/lakehouse/default/Files/dlt_ingestion"
    )


def get_connectors_path() -> str:
    """Get path to connectors directory."""
    return f"{get_base_path()}/connectors"


def get_configs_path() -> str:
    """Get path to configs directory."""
    return f"{get_base_path()}/configs"


def get_logs_path() -> str:
    """Get path to logs directory."""
    return f"{get_base_path()}/logs"


def get_state_path() -> str:
    """Get path to state directory."""
    return f"{get_base_path()}/state"


def ensure_dir(path: str) -> None:
    """
    Ensure a directory exists, creating it if necessary.

    For lakehouse paths, uses notebookutils if available.

    Args:
        path: Directory path to ensure exists
    """
    try:
        import notebookutils
        notebookutils.fs.mkdirs(path)
    except ImportError:
        os.makedirs(path, exist_ok=True)


def list_files(directory: str, pattern: str = "*") -> list:
    """
    List files in a directory matching a pattern.

    Args:
        directory: Directory to list
        pattern: Glob pattern (default: all files)

    Returns:
        List of file paths
    """
    try:
        import notebookutils
        files = notebookutils.fs.ls(directory)
        return [f.path for f in files if f.name.endswith(pattern.replace("*", ""))]
    except ImportError:
        from glob import glob
        return glob(f"{directory}/{pattern}")


def file_exists(path: str) -> bool:
    """
    Check if a file exists.

    Args:
        path: File path to check

    Returns:
        True if file exists
    """
    try:
        import notebookutils
        return notebookutils.fs.exists(path)
    except ImportError:
        return os.path.exists(path)
