import logging
from typing import Dict, Any

import pandas as pd

from ..config import config
from ..utils import (
    ensure_datetime_column,
    filter_lightning_data_by_date_range,
    load_json_data,
    normalize_local_time_to_timezone,
    validate_lightning_data,
    validate_turbine_data,
)

logger = logging.getLogger(__name__)


def _rename_columns_for_lightning(df: pd.DataFrame) -> pd.DataFrame:
    required = {
        "lat": ["lat", "latitude"],
        "lng": ["lng", "lon", "longitude", "long"],
        "current": ["current", "amplitude", "amp", "peak_current"],
        "p_type": ["p_type", "ptype", "type", "flash_type"],
        "local_time": ["local_time", "time", "time_utc", "timestamp", "datetime", "date_time", "localtime"],
    }

    columns_lower = {col.lower(): col for col in df.columns}
    rename_map: Dict[str, str] = {}

    for target, candidates in required.items():
        found_source = None
        for candidate in candidates:
            source = columns_lower.get(candidate.lower())
            if source is not None:
                found_source = source
                break
        if found_source is not None and found_source != target:
            rename_map[found_source] = target

    if rename_map:
        df = df.rename(columns=rename_map)

    missing = [col for col in ["lat", "lng", "current", "p_type", "local_time"] if col not in df.columns]
    if missing:
        raise ValueError(f"Missing required lightning columns in CSV: {missing}")

    return df


def load_lightning_data_from_csv(csv_path: str | None = None) -> pd.DataFrame:
    """
    Load and validate lightning data from a CSV file.

    Args:
        csv_path: Path to lightning CSV file. If None, uses config.lightning_csv.

    Returns:
        DataFrame containing lightning data
    """
    if csv_path is None:
        csv_path = getattr(config, "lightning_csv", None)
        if csv_path is None:
            raise ValueError("lightning_csv path must be provided (not available in config)")

    logger.info(f"Loading lightning data from CSV {csv_path}")

    try:
        df = pd.read_csv(csv_path)

        if len(df) == 0:
            logger.warning(
                "No lightning records found in CSV - creating empty DataFrame with required columns",
            )
            df = pd.DataFrame(columns=["lat", "lng", "current", "p_type", "local_time"])
        else:
            df = _rename_columns_for_lightning(df)

        if not validate_lightning_data(df):
            raise ValueError("Lightning data validation failed for CSV source")

        df = ensure_datetime_column(df, "local_time")

        if "current_abs" not in df.columns and len(df) > 0:
            df["current_abs"] = df["current"].abs()
        elif "current_abs" not in df.columns and len(df) == 0:
            df["current_abs"] = pd.Series(dtype="float64")

        start_date = getattr(config, "analysis_start_date", None)
        end_date = getattr(config, "analysis_end_date", None)

        if start_date and end_date:
            df = filter_lightning_data_by_date_range(df, start_date, end_date)

        farm_tz = getattr(config, "timezone", None)
        if len(df) > 0 and farm_tz:
            df = normalize_local_time_to_timezone(df, "local_time", farm_tz)

        logger.info(f"Successfully loaded {len(df)} lightning records from CSV")
        return df

    except Exception as e:
        logger.error(f"Failed to load lightning data from CSV: {e}")
        raise


def load_lightning_data(json_path: str = None) -> pd.DataFrame:
    """
    Load and validate lightning data from configured source.

    If config.lightning_source_type == \"csv\" and no explicit json_path is provided,
    data will be loaded from CSV. Otherwise, API/JSON loading is used.
    """
    if json_path is None:
        source_type = getattr(config, "lightning_source_type", "api")
        if source_type == "csv":
            return load_lightning_data_from_csv()

        json_path = getattr(config, "lightning_json", None)
        if json_path is None:
            raise ValueError("lightning_json path must be provided (not available in config)")

    logger.info(f"Loading lightning data from JSON {json_path}")

    try:
        data = load_json_data(json_path)

        if isinstance(data, dict) and len(data) > 0:
            if "data" in data and isinstance(data["data"], list):
                records = data["data"]
            else:
                records = list(data.values())[0]
        else:
            records = data

        df = pd.DataFrame(records)

        if len(df) == 0:
            logger.warning("No lightning records found in data - creating empty DataFrame with required columns")
            df = pd.DataFrame(columns=["lat", "lng", "current", "p_type", "local_time"])

        if not validate_lightning_data(df):
            raise ValueError("Lightning data validation failed")

        df = ensure_datetime_column(df, "local_time")

        if "current_abs" not in df.columns and len(df) > 0:
            df["current_abs"] = df["current"].abs()
        elif "current_abs" not in df.columns and len(df) == 0:
            df["current_abs"] = pd.Series(dtype="float64")

        start_date = getattr(config, "analysis_start_date", None)
        end_date = getattr(config, "analysis_end_date", None)

        if start_date and end_date:
            df = filter_lightning_data_by_date_range(df, start_date, end_date)

        farm_tz = getattr(config, "timezone", None)
        if len(df) > 0 and farm_tz:
            df = normalize_local_time_to_timezone(df, "local_time", farm_tz)

        logger.info(f"Successfully loaded {len(df)} lightning records")
        return df

    except Exception as e:
        logger.error(f"Failed to load lightning data: {e}")
        raise

def load_turbine_data(json_path: str = None) -> pd.DataFrame:
    """
    Load and validate turbine data from JSON file.
    
    Args:
        json_path: Path to turbine JSON file. If None, uses config default.
        
    Returns:
        DataFrame containing turbine data
        
    Raises:
        ValueError: If data validation fails
    """
    if json_path is None:
        json_path = getattr(config, 'turbine_json', None)
        if json_path is None:
            raise ValueError("turbine_json path must be provided (not available in config)")
    
    logger.info(f"Loading turbine data from {json_path}")
    
    try:
        # Load JSON data
        data = load_json_data(json_path)
        
        # Create DataFrame
        df = pd.DataFrame(data)
        
        # Validate data
        if not validate_turbine_data(df):
            raise ValueError("Turbine data validation failed")
        
        logger.info(f"Successfully loaded {len(df)} turbine records")
        return df
        
    except Exception as e:
        logger.error(f"Failed to load turbine data: {e}")
        raise
