"""Models for P1 Monitor."""

from __future__ import annotations

from dataclasses import dataclass
from enum import Enum
from typing import Any


class EnergyTariff(str, Enum):
    """Enumeration representing the rate period."""

    __slots__ = ()

    LOW = "low"
    HIGH = "high"


@dataclass
class SmartMeter:
    """Object representing an SmartMeter response from P1 Monitor."""

    gas_consumption: float | None
    energy_tariff_period: str | None

    power_consumption: int | None
    energy_consumption_high: float | None
    energy_consumption_low: float | None

    power_production: int | None
    energy_production_high: float | None
    energy_production_low: float | None

    @staticmethod
    def from_dict(data: dict[str | int, Any]) -> SmartMeter:
        """Return SmartMeter object from the P1 Monitor API response.

        Args:
        ----
            data: The data from the P1 Monitor API.

        Returns:
        -------
            A SmartMeter object.

        """

        def energy_tariff(tariff: str) -> EnergyTariff:
            """Return API energy_tariff information.

            Args:
            ----
                tariff: The provided tariff code from the API.

            Returns:
            -------
                The energy tariff period class.

            """
            if tariff == "P":
                return EnergyTariff.HIGH
            return EnergyTariff.LOW

        data = data[0]
        return SmartMeter(
            gas_consumption=data.get("CONSUMPTION_GAS_M3"),
            power_consumption=data.get("CONSUMPTION_W"),
            energy_consumption_high=data.get("CONSUMPTION_KWH_HIGH"),
            energy_consumption_low=data.get("CONSUMPTION_KWH_LOW"),
            power_production=data.get("PRODUCTION_W"),
            energy_production_high=data.get("PRODUCTION_KWH_HIGH"),
            energy_production_low=data.get("PRODUCTION_KWH_LOW"),
            energy_tariff_period=energy_tariff(str(data.get("TARIFCODE"))),
        )


@dataclass
class Settings:
    """Object representing an Settings response from P1 Monitor."""

    gas_consumption_price: float | None

    energy_consumption_price_high: float | None
    energy_consumption_price_low: float | None

    energy_production_price_high: float | None
    energy_production_price_low: float | None

    @staticmethod
    def from_dict(data: dict[str, Any]) -> Settings:
        """Return Settings object from the P1 Monitor API response.

        Args:
        ----
            data: The data from the P1 Monitor API.

        Returns:
        -------
            A Settings object.

        """
        return Settings(
            gas_consumption_price=search(15, data, "conf"),
            energy_consumption_price_low=search(1, data, "conf"),
            energy_consumption_price_high=search(2, data, "conf"),
            energy_production_price_low=search(3, data, "conf"),
            energy_production_price_high=search(4, data, "conf"),
        )


@dataclass
class Phases:
    """Object representing an Phases response from P1 Monitor."""

    voltage_phase_l1: float | None
    voltage_phase_l2: float | None
    voltage_phase_l3: float | None

    current_phase_l1: float | None
    current_phase_l2: float | None
    current_phase_l3: float | None

    power_consumed_phase_l1: int | None
    power_consumed_phase_l2: int | None
    power_consumed_phase_l3: int | None

    power_produced_phase_l1: int | None
    power_produced_phase_l2: int | None
    power_produced_phase_l3: int | None

    @staticmethod
    def from_dict(data: dict[str | int, Any]) -> Phases:
        """Return Phases object from the P1 Monitor API response.

        Args:
        ----
            data: The data from the P1 Monitor API.

        Returns:
        -------
            A Phases object.

        """
        return Phases(
            voltage_phase_l1=search(103, data, "status"),
            voltage_phase_l2=search(104, data, "status"),
            voltage_phase_l3=search(105, data, "status"),
            current_phase_l1=search(100, data, "status"),
            current_phase_l2=search(101, data, "status"),
            current_phase_l3=search(102, data, "status"),
            power_consumed_phase_l1=convert(search(74, data, "status")),
            power_consumed_phase_l2=convert(search(75, data, "status")),
            power_consumed_phase_l3=convert(search(76, data, "status")),
            power_produced_phase_l1=convert(search(77, data, "status")),
            power_produced_phase_l2=convert(search(78, data, "status")),
            power_produced_phase_l3=convert(search(79, data, "status")),
        )


@dataclass
class WaterMeter:
    """Object representing an WaterMeter response from P1 Monitor."""

    consumption_day: int | None
    consumption_total: float | None
    pulse_count: int | None

    @staticmethod
    def from_dict(data: dict[str | int, Any]) -> WaterMeter:
        """Return WaterMeter object from the P1 Monitor API response.

        Args:
        ----
            data: The data from the P1 Monitor API.

        Returns:
        -------
            A WaterMeter object.

        """
        data = data[0]
        return WaterMeter(
            consumption_day=data.get("WATERMETER_CONSUMPTION_LITER"),
            consumption_total=data.get("WATERMETER_CONSUMPTION_TOTAL_M3"),
            pulse_count=data.get("WATERMETER_PULS_COUNT"),
        )


def search(position: int, data: Any, service: str) -> float:
    """Find the correct value in the json data file.

    Args:
    ----
        position: The position ID number.
        data: The JSON list which is requested from the API.
        service: Type of dataclass.

    Returns:
    -------
        The value that corresponds to the specified position.

    """
    value: float
    for i in data:
        if service == "conf" and i["CONFIGURATION_ID"] == position:
            value = float(i["PARAMETER"])
        elif service == "status" and i["STATUS_ID"] == position:
            value = float(i["STATUS"])
    return value


def convert(value: float) -> int:
    """Convert values from kW to W.

    Args:
    ----
        value: The current value.

    Returns:
    -------
        Value in Watt (W).

    """
    return int(float(value) * 1000)
