"""Implementation of the usage interface."""

from __future__ import annotations

from datetime import datetime

from ..iotmodule import IotModule, merge


class Usage(IotModule):
    """Baseclass for emeter/usage interfaces."""

    def query(self) -> dict:
        """Return the base query."""
        now = datetime.now()
        year = now.year
        month = now.month

        req = self.query_for_command("get_realtime")
        req = merge(
            req, self.query_for_command("get_daystat", {"year": year, "month": month})
        )
        req = merge(req, self.query_for_command("get_monthstat", {"year": year}))

        return req

    @property
    def estimated_query_response_size(self) -> int:
        """Estimated maximum query response size."""
        return 2048

    @property
    def daily_data(self) -> list[dict]:
        """Return statistics on daily basis."""
        return self.data["get_daystat"]["day_list"]

    @property
    def monthly_data(self) -> list[dict]:
        """Return statistics on monthly basis."""
        return self.data["get_monthstat"]["month_list"]

    @property
    def usage_today(self) -> int | None:
        """Return today's usage in minutes."""
        today = datetime.now().day
        # Traverse the list in reverse order to find the latest entry.
        for entry in reversed(self.daily_data):
            if entry["day"] == today:
                return entry["time"]
        return None

    @property
    def usage_this_month(self) -> int | None:
        """Return usage in this month in minutes."""
        this_month = datetime.now().month
        # Traverse the list in reverse order to find the latest entry.
        for entry in reversed(self.monthly_data):
            if entry["month"] == this_month:
                return entry["time"]
        return None

    async def get_raw_daystat(
        self, *, year: int | None = None, month: int | None = None
    ) -> dict:
        """Return raw daily stats for the given year & month."""
        if year is None:
            year = datetime.now().year
        if month is None:
            month = datetime.now().month

        return await self.call("get_daystat", {"year": year, "month": month})

    async def get_raw_monthstat(self, *, year: int | None = None) -> dict:
        """Return raw monthly stats for the given year."""
        if year is None:
            year = datetime.now().year

        return await self.call("get_monthstat", {"year": year})

    async def get_daystat(
        self, *, year: int | None = None, month: int | None = None
    ) -> dict:
        """Return daily stats for the given year & month.

        The return value is a dictionary of {day: time, ...}.
        """
        data = await self.get_raw_daystat(year=year, month=month)
        data = self._convert_stat_data(data["day_list"], entry_key="day")
        return data

    async def get_monthstat(self, *, year: int | None = None) -> dict:
        """Return monthly stats for the given year.

        The return value is a dictionary of {month: time, ...}.
        """
        data = await self.get_raw_monthstat(year=year)
        data = self._convert_stat_data(data["month_list"], entry_key="month")
        return data

    async def erase_stats(self) -> dict:
        """Erase all stats."""
        return await self.call("erase_runtime_stat")

    def _convert_stat_data(self, data: list[dict], entry_key: str) -> dict:
        """Return usage information keyed with the day/month.

        The incoming data is a list of dictionaries::

               [{'year':      int,
                 'month':     int,
                 'day':       int,     <-- for get_daystat not get_monthstat
                 'time':      int,     <-- for usage (mins)
               }, ...]

        :return: return a dictionary keyed by day or month with time as the value.
        """
        if not data:
            return {}

        res = {entry[entry_key]: entry["time"] for entry in data}

        return res
