"""
Common helper functions for entities across platforms.

This module provides utility functions used by both sensor and binary_sensor platforms:
- Price value conversion (major/subunit currency units)

- Time-based calculations (rolling hour center index)

These functions operate on entity-level concepts (states, translations) but are
platform-agnostic and can be used by both sensor and binary_sensor platforms.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from custom_components.tibber_prices.const import get_display_precision, get_display_unit_factor

if TYPE_CHECKING:
    from datetime import datetime

    from custom_components.tibber_prices.coordinator.time_service import TibberPricesTimeService
    from custom_components.tibber_prices.data import TibberPricesConfigEntry
    from homeassistant.config_entries import ConfigEntry


def get_price_value(
    price: float,
    *,
    in_euro: bool | None = None,
    config_entry: ConfigEntry | TibberPricesConfigEntry | None = None,
) -> float:
    """
    Convert price based on unit.

    NOTE: This function supports two modes for backward compatibility:
    1. Legacy mode: in_euro=True/False (hardcoded conversion)
    2. New mode: config_entry (config-driven conversion)

    New code should use get_display_unit_factor(config_entry) directly.

    Args:
        price: Price value to convert.
        in_euro: (Legacy) If True, return in base currency; if False, in subunit currency.
        config_entry: (New) Config entry to get display unit configuration.

    Returns:
        Price in requested unit (major or subunit currency units).

    """
    # Legacy mode: use in_euro parameter
    if in_euro is not None:
        return price if in_euro else round(price * 100, 2)

    # New mode: use config_entry
    if config_entry is not None:
        factor = get_display_unit_factor(config_entry)
        precision = get_display_precision(config_entry)
        return round(price * factor, precision)

    # Fallback: default to subunit currency (backward compatibility)
    return round(price * 100, 2)


def find_rolling_hour_center_index(
    all_prices: list[dict],
    current_time: datetime,
    hour_offset: int,
    *,
    time: TibberPricesTimeService,
) -> int | None:
    """
    Find the center index for the rolling hour window.

    Args:
        all_prices: List of all price interval dictionaries with 'startsAt' key
        current_time: Current datetime to find the current interval
        hour_offset: Number of hours to offset from current interval (can be negative)
        time: TibberPricesTimeService instance (required)

    Returns:
        Index of the center interval for the rolling hour window, or None if not found

    """
    # Round to nearest interval boundary to handle edge cases where HA schedules
    # us slightly before the boundary (e.g., 14:59:59.999 → 15:00:00)
    target_time = time.round_to_nearest_quarter(current_time)
    current_idx = None

    for idx, price_data in enumerate(all_prices):
        starts_at = time.get_interval_time(price_data)
        if starts_at is None:
            continue

        # Exact match after rounding
        if starts_at == target_time:
            current_idx = idx
            break

    if current_idx is None:
        return None

    return current_idx + (hour_offset * 4)
