"""Organization directory utilities."""

from datetime import datetime
from pathlib import Path
from typing import Any, Dict

import yaml


def get_org_dir(org_name: str, root: Path = None) -> Path:
    """Get the organization directory path."""
    if root is None:
        # Check if we're already in cloudzero-demo-billing directory
        current_dir = Path.cwd()
        if (current_dir / "orgs").exists():
            root = Path("orgs")
        else:
            root = Path("cloudzero-demo-billing") / "orgs"
    return root / org_name


def get_run_dir(
    org_dir: Path, timestamp: str = None, run_type: str = "billing"
) -> Path:
    """Get a specific run directory path for billing or telemetry."""
    if timestamp is None:
        # Find the most recent run
        runs_dir = org_dir / run_type / "runs"
        if not runs_dir.exists():
            raise ValueError(f"No runs directory found at {runs_dir}")

        valid_runs = sorted(runs_dir.glob("*"), key=lambda p: p.name)
        valid_run_names = [p.name for p in valid_runs if p.is_dir()]

        if not valid_run_names:
            raise ValueError(f"No valid run folders found in {runs_dir}")

        timestamp = valid_run_names[-1]  # Most recent

    return org_dir / run_type / "runs" / timestamp


def create_run_dir(org_dir: Path, run_type: str = "billing") -> Path:
    """Create a new run directory with timestamp for billing or telemetry."""
    timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")
    run_dir = org_dir / run_type / "runs" / timestamp
    run_dir.mkdir(parents=True, exist_ok=True)
    return run_dir


def get_billing_run_dir(org_dir: Path, timestamp: str = None) -> Path:
    """Get a billing run directory path."""
    return get_run_dir(org_dir, timestamp, "billing")


def get_telemetry_run_dir(org_dir: Path, timestamp: str = None) -> Path:
    """Get a telemetry run directory path."""
    return get_run_dir(org_dir, timestamp, "telemetry")


def create_billing_run_dir(org_dir: Path) -> Path:
    """Create a new billing run directory with timestamp and corresponding log directory."""
    run_dir = create_run_dir(org_dir, "billing")

    # Create corresponding log directory for run-aligned logging
    org_name = org_dir.name
    run_id = run_dir.name
    ensure_log_run_dir(org_name, run_id)

    return run_dir


def ensure_log_run_dir(org_name: str, run_id: str) -> Path:
    """
    Ensure log directory exists that mirrors pipeline run directory.

    Creates the run-aligned log directory structure:
    logs/{org_name}/runs/{run_id}/

    Args:
        org_name: Organization name
        run_id: Run identifier (timestamp format YYYY-MM-DD_HHMMSS)

    Returns:
        Path to the created log run directory
    """
    log_run_dir = Path("logs") / org_name / "runs" / run_id
    log_run_dir.mkdir(parents=True, exist_ok=True)
    return log_run_dir


def create_telemetry_run_dir(org_dir: Path) -> Path:
    """Create a new telemetry run directory with timestamp."""
    return create_run_dir(org_dir, "telemetry")


def load_billing_configs(
    org_dir: Path, stage_name: str = None, verbose: bool = False, run_dir: Path = None
) -> Dict[str, Any]:
    """
    Load billing configuration(s) using the new multi-config system.

    This function replaces the old single-config loading with automatic
    discovery and merging of multiple .pipeline.yaml files.

    Args:
        org_dir: Organization directory path
        stage_name: Specific stage to load configs for (optional for backward compatibility)
        verbose: Whether to print detailed progress information
        run_dir: Run directory to write job metadata mapping file (optional)

    Returns:
        Merged configuration dictionary compatible with existing pipeline

    Raises:
        ValueError: If config loading fails
    """
    try:
        from .multi_config_loader import MultiConfigError, load_multi_pipeline_configs

        # If no stage specified, try to load all stages (for backward compatibility)
        if stage_name is None:
            # For backward compatibility, we'll try to detect the stage from context
            # or load a representative config. In practice, callers should specify stage_name.
            print(
                "⚠️  Warning: stage_name not specified. Using multi-config discovery for all stages."
            )

            # Discover configs to see what stages are available
            from .config_discovery import discover_and_validate_configs

            config_files = discover_and_validate_configs(org_dir, verbose=False)

            # Find all stages across all configs
            all_stages = set()
            for config_file in config_files:
                content = config_file.load_content()
                all_stages.update(content.get("stages", {}).keys())

            if not all_stages:
                raise ValueError("No stages found in any configuration files")

            # Load configs for all discovered stages
            merged_config = {"stages": {}}
            for stage in all_stages:
                try:
                    stage_config = load_multi_pipeline_configs(
                        org_dir, stage, verbose=verbose, run_dir=run_dir
                    )
                    merged_config["stages"].update(stage_config["stages"])
                except MultiConfigError:
                    # Skip stages that have no jobs
                    continue

            return merged_config
        else:
            # Load configs for specific stage (recommended path)
            return load_multi_pipeline_configs(
                org_dir, stage_name, verbose=verbose, run_dir=run_dir
            )

    except MultiConfigError as e:
        raise ValueError(f"Multi-config loading failed: {e}")
    except Exception as e:
        raise ValueError(f"Unexpected error loading billing configs: {e}")


def load_telemetry_configs(
    org_dir: Path, config_type: str = "unit-metrics"
) -> Dict[str, Any]:
    """Load telemetry configuration from telemetry/configs/ directory.

    Args:
        org_dir: Organization directory path
        config_type: Type of config to load (unit-metrics, allocations, etc.)

    Returns:
        Configuration dictionary
    """
    configs_dir = org_dir / "telemetry" / "configs"
    config_path = configs_dir / f"{config_type}.yaml"

    if not config_path.exists():
        # Try .yml extension
        config_path = configs_dir / f"{config_type}.yml"
        if not config_path.exists():
            raise FileNotFoundError(f"Telemetry config file not found: {config_path}")

    with open(config_path) as f:
        return yaml.safe_load(f)


def get_billing_config_path(org_dir: Path, config_file: str = None) -> Path:
    """Get the path to a billing configuration file.

    Args:
        org_dir: Organization directory path
        config_file: Specific config file name, defaults to 'main.yaml'

    Returns:
        Path to the configuration file
    """
    if config_file is None:
        config_file = "main.yaml"

    return org_dir / "billing" / "pipeline-configs" / config_file
