# pylint: disable=import-outside-toplevel,broad-exception-caught
"""Configuration loader utilities for VideoRAG and processors."""

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


def load_video_rag_config(config_path: Optional[str] = None) -> Dict[str, Any]:
    """
    Load VideoRAG configuration from YAML file.

    Args:
        config_path: Path to config file. If None, searches for video_rag_config.yml
                    in config/ directory and project root.

    Returns:
        Dict with configuration data

    Raises:
        FileNotFoundError: If config file not found
        yaml.YAMLError: If config file is invalid

    Example:
        config = load_video_rag_config()
        print(config['video_rag']['enable_subtitle_check'])
    """
    if config_path is None:
        config_path = os.environ.get("VIDEORAG_CONFIG_FILE")

        if config_path is None:
            search_paths = [
                "config/video_rag_config.yml",
                "../config/video_rag_config.yml",
            ]

            for path in search_paths:
                if os.path.exists(path):
                    config_path = path
                    break

        if config_path is None:
            raise FileNotFoundError(
                "video_rag_config.yml not found in config/ folder. "
                "Please copy config/video_rag_config.example.yml to config/video_rag_config.yml "
                "and customize it for your needs."
            )

    config_path = Path(config_path).resolve()

    if not config_path.exists():
        raise FileNotFoundError(f"Config file not found: {config_path}")

    with open(config_path, "r", encoding="utf-8") as f:
        config = yaml.safe_load(f)

    return config


def get_processor_config(config: Dict[str, Any], processor_name: str) -> Dict[str, Any]:
    """
    Extract processor configuration from config dict.

    Args:
        config: Full configuration dict from load_video_rag_config()
        processor_name: Name of processor (e.g., 'ocr', 'object_detection')

    Returns:
        Dict with processor configuration

    Example:
        config = load_video_rag_config()
        ocr_config = get_processor_config(config, 'ocr')
        print(ocr_config['enable_stopword_filtering'])
    """
    processors = config.get("processors", {})
    return processors.get(processor_name, {})


def get_video_rag_config(config: Dict[str, Any]) -> Dict[str, Any]:
    """
    Extract VideoRAG-specific configuration.

    Args:
        config: Full configuration dict from load_video_rag_config()

    Returns:
        Dict with VideoRAG configuration

    Example:
        config = load_video_rag_config()
        rag_config = get_video_rag_config(config)
        print(rag_config['enable_subtitle_check'])
    """
    return config.get("video_rag", {})


def create_processor_factory_from_config(
    config: Dict[str, Any], openai_client=None
) -> "ProcessorFactory":
    """
    Create ProcessorFactory from configuration with custom processor support.

    Supports custom processors defined in YAML:
        custom_processors:
          - processor_type: scene_detection
            provider: opencv
            class_path: "my_package.processors:OpenCVSceneDetector"
            default: true

    Args:
        config: Configuration dict from load_video_rag_config()
        openai_client: Optional OpenAI client instance (required for transcription)

    Returns:
        Configured ProcessorFactory instance with custom processors registered

    Example:
        from openai import OpenAI
        config = load_video_rag_config()
        factory = create_processor_factory_from_config(config, OpenAI())
    """
    from mini_videorag.processors import ProcessorFactory
    import logging

    logger = logging.getLogger(__name__)

    processor_config = config.get("processors", {}).copy()

    if openai_client and "transcription" in processor_config:
        processor_config["transcription"]["openai_client"] = openai_client

    factory = ProcessorFactory(processor_config)

    custom_processors = config.get("custom_processors", [])
    if custom_processors:
        logger.info(f"Registering {len(custom_processors)} custom processor(s) from config")

        for proc_config in custom_processors:
            processor_type = proc_config.get("processor_type")
            provider = proc_config.get("provider")
            class_path = proc_config.get("class_path")
            set_as_default = proc_config.get("default", False)

            if not all([processor_type, provider, class_path]):
                logger.warning(
                    f"Skipping invalid custom processor config (missing required fields): {proc_config}"
                )
                continue

            try:
                factory.register_processor(
                    processor_type=processor_type,
                    provider=provider,
                    class_path=class_path,
                    set_as_default=set_as_default,
                )
                logger.info(
                    f"Registered custom processor: {processor_type}.{provider} "
                    f"(default={set_as_default})"
                )
            except Exception as e:
                logger.error(
                    f"Failed to register custom processor {processor_type}.{provider}: {e}"
                )
                continue

    return factory


def create_pipeline_from_config(config: Dict[str, Any], openai_client=None) -> "ProcessorPipeline":
    """
    Create ProcessorPipeline from configuration.

    Args:
        config: Configuration dict from load_video_rag_config()
        openai_client: Optional OpenAI client instance (required for transcription)

    Returns:
        Configured ProcessorPipeline instance

    Example:
        from openai import OpenAI
        config = load_video_rag_config()
        pipeline = create_pipeline_from_config(config, OpenAI())
    """
    from mini_videorag.core.pipeline import ProcessorPipeline
    from mini_videorag.types import WorkflowStepConfig
    from mini_videorag.utils.output_manager import OutputManager

    factory = create_processor_factory_from_config(config, openai_client)

    workflow_config = config.get("workflow", {})

    workflow = {}
    for proc_name, proc_config in workflow_config.items():
        if proc_config.get("enabled", True):
            workflow[proc_name] = WorkflowStepConfig(
                depends_on=proc_config.get("depends_on", []),
                enabled=proc_config.get("enabled", True),
            )

    output_manager = None
    outputs_config = config.get("outputs", {})
    if outputs_config.get("enabled", False):
        output_manager = OutputManager(config)

    return ProcessorPipeline(
        processor_factory=factory,
        workflow=workflow if workflow else None,
        output_manager=output_manager,
    )
