"""
Data averaging functions for RSN sensors.

Averages sensor data over specified time windows.
"""

import numpy as np
import logging
from typing import Tuple
from datetime import datetime

logger = logging.getLogger(__name__)


def average_rsn_data(
    acceleration: np.ndarray,
    timestamps: np.ndarray,
    temperature: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Average RSN Link data over time windows.

    Converts MATLAB MediaDati_RSN.m function.

    Args:
        acceleration: Acceleration data array (timestamps x axes)
        timestamps: Array of timestamps (datetime or numeric)
        temperature: Temperature data array
        n_points: Number of points to average

    Returns:
        Tuple of (averaged_angles, averaged_timestamps, averaged_temperature)
    """
    logger.info(f"Averaging RSN data with window size {n_points}")

    if len(acceleration) < n_points:
        logger.warning(f"Not enough data points ({len(acceleration)}) for averaging window ({n_points})")
        return acceleration, timestamps, temperature

    # Calculate number of averaged samples
    n_samples = len(acceleration) // n_points

    # Initialize output arrays
    angles_avg = np.zeros((n_samples, acceleration.shape[1]))
    temp_avg = np.zeros((n_samples, temperature.shape[1]))
    time_avg = np.zeros(n_samples)

    # Perform averaging
    for i in range(n_samples):
        start_idx = i * n_points
        end_idx = start_idx + n_points

        # Average acceleration (convert to angles)
        angles_avg[i, :] = np.mean(acceleration[start_idx:end_idx, :], axis=0)

        # Average temperature
        temp_avg[i, :] = np.mean(temperature[start_idx:end_idx, :], axis=0)

        # Use middle timestamp of window
        time_avg[i] = timestamps[start_idx + n_points // 2]

    logger.info(f"Averaged {len(acceleration)} samples to {n_samples} samples")
    return angles_avg, time_avg, temp_avg


def average_rsn_hr_data(
    angle_data: np.ndarray,
    timestamps: np.ndarray,
    temperature: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Average RSN Link HR data over time windows.

    Converts MATLAB MediaDati_RSNHR.m function.

    Args:
        angle_data: Angle data array
        timestamps: Array of timestamps
        temperature: Temperature data array
        n_points: Number of points to average

    Returns:
        Tuple of (averaged_angles, averaged_timestamps, averaged_temperature)
    """
    logger.info(f"Averaging RSN HR data with window size {n_points}")

    if len(angle_data) < n_points:
        logger.warning(f"Not enough data points for averaging")
        return angle_data, timestamps, temperature

    n_samples = len(angle_data) // n_points

    angles_avg = np.zeros((n_samples, angle_data.shape[1]))
    temp_avg = np.zeros((n_samples, temperature.shape[1]))
    time_avg = np.zeros(n_samples)

    for i in range(n_samples):
        start_idx = i * n_points
        end_idx = start_idx + n_points

        angles_avg[i, :] = np.mean(angle_data[start_idx:end_idx, :], axis=0)
        temp_avg[i, :] = np.mean(temperature[start_idx:end_idx, :], axis=0)
        time_avg[i] = timestamps[start_idx + n_points // 2]

    logger.info(f"Averaged to {n_samples} samples")
    return angles_avg, time_avg, temp_avg


def average_load_link_data(
    load_data: np.ndarray,
    timestamps: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray]:
    """
    Average Load Link data over time windows.

    Converts MATLAB MediaDati_LL.m function.

    Args:
        load_data: Load data array
        timestamps: Array of timestamps
        n_points: Number of points to average

    Returns:
        Tuple of (averaged_load, averaged_timestamps)
    """
    logger.info(f"Averaging Load Link data with window size {n_points}")

    if len(load_data) < n_points:
        logger.warning(f"Not enough data points for averaging")
        return load_data, timestamps

    n_samples = len(load_data) // n_points

    load_avg = np.zeros((n_samples, load_data.shape[1]))
    time_avg = np.zeros(n_samples)

    for i in range(n_samples):
        start_idx = i * n_points
        end_idx = start_idx + n_points

        load_avg[i, :] = np.mean(load_data[start_idx:end_idx, :], axis=0)
        time_avg[i] = timestamps[start_idx + n_points // 2]

    logger.info(f"Averaged to {n_samples} samples")
    return load_avg, time_avg
