from decimal import Decimal
import logging
from typing import cast

from homeassistant.const import CONF_ENTITY_ID, CONF_NAME, CONF_UNIQUE_ID, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.typing import ConfigType

from custom_components.powercalc.const import (
    CONF_CREATE_ENERGY_SENSORS,
    CONF_SUBTRACT_ENTITIES,
    CONF_UTILITY_METER_NET_CONSUMPTION,
    GroupType,
)
from custom_components.powercalc.errors import SensorConfigurationError
from custom_components.powercalc.sensors.abstract import generate_power_sensor_entity_id, generate_power_sensor_name
from custom_components.powercalc.sensors.energy import create_energy_sensor
from custom_components.powercalc.sensors.energy_related import create_energy_related_sensors
from custom_components.powercalc.sensors.group.custom import GroupedPowerSensor

_LOGGER = logging.getLogger(__name__)


def create_subtract_group_sensors(
    hass: HomeAssistant,
    config: ConfigType,
) -> list[Entity]:
    """Create subtract group sensors."""

    validate_config(config)
    group_name = str(config.get(CONF_NAME))
    base_entity_id = str(config.get(CONF_ENTITY_ID))
    subtract_entities = cast(list[str], config.get(CONF_SUBTRACT_ENTITIES))

    name = generate_power_sensor_name(config, group_name)
    unique_id = config.get(CONF_UNIQUE_ID, generate_unique_id(config))
    entity_id = generate_power_sensor_entity_id(
        hass,
        config,
        name=group_name,
        unique_id=unique_id,
    )

    _LOGGER.debug("Creating grouped power sensor: %s (entity_id=%s)", name, entity_id)

    sensors: list[Entity] = []
    power_sensor = SubtractGroupSensor(
        hass,
        name,
        config,
        entity_id,
        base_entity_id,
        subtract_entities,
        unique_id=unique_id,
    )
    sensors.append(power_sensor)
    if config.get(CONF_CREATE_ENERGY_SENSORS):
        energy_sensor = create_energy_sensor(
            hass,
            config,
            power_sensor,
        )
        sensors.append(energy_sensor)

        config[CONF_UTILITY_METER_NET_CONSUMPTION] = True
        sensors.extend(create_energy_related_sensors(hass, config, energy_sensor))
    return sensors


def generate_unique_id(sensor_config: ConfigType) -> str:
    """Generate unique_id for subtract group sensor."""
    base_entity_id = str(sensor_config[CONF_ENTITY_ID])
    return f"pc_subtract_{base_entity_id}"


def validate_config(config: ConfigType) -> None:
    """Validate subtract group sensor configuration."""
    if CONF_NAME not in config:
        raise SensorConfigurationError("name is required")

    if CONF_ENTITY_ID not in config:
        raise SensorConfigurationError("entity_id is required")

    if CONF_SUBTRACT_ENTITIES not in config:
        raise SensorConfigurationError("subtract_entities is required")


class SubtractGroupSensor(GroupedPowerSensor):
    def __init__(
        self,
        hass: HomeAssistant,
        name: str,
        sensor_config: ConfigType,
        entity_id: str,
        base_entity_id: str,
        subtract_entities: list[str],
        unique_id: str | None = None,
    ) -> None:
        all_entities = {base_entity_id, *subtract_entities}

        super().__init__(
            hass=hass,
            name=name,
            entities=all_entities,
            entity_id=entity_id,
            sensor_config=sensor_config,
            group_type=GroupType.SUBTRACT,
            unique_id=unique_id,
        )

        self._base_entity_id = base_entity_id
        self._subtract_entities = subtract_entities

    def get_summed_state(self) -> Decimal | str:
        base_value = self._member_states.get(self._base_entity_id)
        if base_value is None:
            return STATE_UNAVAILABLE
        subtracted_value = base_value
        for entity_id in self._subtract_entities:
            subtracted_value -= self._member_states.get(entity_id, 0)
        return subtracted_value
