from decimal import Decimal
import logging

from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.const import CONF_ENTITIES, STATE_CLOSING, STATE_ON, STATE_OPENING, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant, State
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import TrackTemplate
import voluptuous as vol

from custom_components.powercalc.const import CONF_POWER, CONF_POWER_OFF, DUMMY_ENTITY_ID

from .strategy_interface import PowerCalculationStrategyInterface

CONFIG_SCHEMA = vol.Schema(
    {
        vol.Optional(CONF_POWER): vol.Coerce(float),
        vol.Optional(CONF_POWER_OFF): vol.Coerce(float),
        vol.Required(CONF_ENTITIES): cv.entities_domain(SWITCH_DOMAIN),
    },
)

_LOGGER = logging.getLogger(__name__)

ON_STATES = [STATE_ON, STATE_OPENING, STATE_CLOSING]


class MultiSwitchStrategy(PowerCalculationStrategyInterface):
    def __init__(
        self,
        hass: HomeAssistant,
        switch_entities: list[str],
        on_power: Decimal,
        off_power: Decimal | None = None,
    ) -> None:
        self.hass = hass
        self.switch_entities = switch_entities
        self.known_states: dict[str, str] | None = None
        self.on_power = on_power
        self.off_power = off_power

    async def calculate(self, entity_state: State) -> Decimal | None:
        if self.known_states is None:
            self.known_states = {
                entity_id: (state.state if (state := self.hass.states.get(entity_id)) else STATE_UNAVAILABLE)
                for entity_id in self.switch_entities
            }

        if entity_state.entity_id != DUMMY_ENTITY_ID and entity_state.entity_id in self.switch_entities:
            self.known_states[entity_state.entity_id] = entity_state.state

        def _get_power(state: str) -> Decimal:
            if state == STATE_UNAVAILABLE:
                return Decimal(0)
            if state in ON_STATES:
                return self.on_power
            return self.off_power or Decimal(0)

        return Decimal(sum(_get_power(state) for state in self.known_states.values()))

    def get_entities_to_track(self) -> list[str | TrackTemplate]:
        return [*self.switch_entities]

    def can_calculate_standby(self) -> bool:
        return self.off_power is not None
