"""
Data Loader Executors

Executors for loading data from various sources.
"""

from __future__ import annotations

from typing import Any, TYPE_CHECKING

import pandas as pd

from .base import NodeExecutor, executor_function

if TYPE_CHECKING:
    from ..schemas import Node
    from ..storage import StorageManager


class CSVLoaderExecutor(NodeExecutor):
    """Executor for loading CSV files."""
    
    def execute(
        self,
        node: "Node",
        input_data: dict[str, Any],
        storage: "StorageManager",
        run_id: str,
    ) -> pd.DataFrame:
        """
        Load a CSV file into a DataFrame.
        
        Parameters:
            - file_path: Path to the CSV file
            - delimiter: Column delimiter (default: ",")
            - has_header: Whether first row is header (default: True)
            - encoding: File encoding (default: "utf-8")
        """
        params = node.data.params
        
        file_path = params.get("file_path", "")
        delimiter = params.get("delimiter", ",")
        has_header = params.get("has_header", True)
        encoding = params.get("encoding", "utf-8")
        na_values = params.get("na_values", ["?", "NA", "N/A", "na", "n/a", "", " ", "null", "NULL", "None", "none", "-"])
        
        if not file_path:
            raise ValueError("file_path is required for CSV loader")
        
        # Resolve file path (could be relative to storage)
        resolved_path = storage.resolve_data_path(file_path)
        
        df = pd.read_csv(
            resolved_path,
            delimiter=delimiter,
            header=0 if has_header else None,
            encoding=encoding,
            na_values=na_values,
        )
        
        # Log the load operation
        storage.log_event(
            run_id=run_id,
            node_id=node.id,
            event="csv_loaded",
            details={
                "file_path": file_path,
                "rows": len(df),
                "columns": list(df.columns),
            },
        )
        
        return df


class JSONLoaderExecutor(NodeExecutor):
    """Executor for loading JSON files."""
    
    def execute(
        self,
        node: "Node",
        input_data: dict[str, Any],
        storage: "StorageManager",
        run_id: str,
    ) -> pd.DataFrame:
        """
        Load a JSON file into a DataFrame.
        
        Parameters:
            - file_path: Path to the JSON file
            - orient: JSON orientation (default: "records")
        """
        params = node.data.params
        
        file_path = params.get("file_path", "")
        orient = params.get("orient", "records")
        
        if not file_path:
            raise ValueError("file_path is required for JSON loader")
        
        resolved_path = storage.resolve_data_path(file_path)
        
        df = pd.read_json(resolved_path, orient=orient)
        
        storage.log_event(
            run_id=run_id,
            node_id=node.id,
            event="json_loaded",
            details={
                "file_path": file_path,
                "rows": len(df),
                "columns": list(df.columns),
            },
        )
        
        return df


# Functional wrappers for engine registration
csv_loader_executor = executor_function(CSVLoaderExecutor)
json_loader_executor = executor_function(JSONLoaderExecutor)
