"""
Setup for Tuya datetime entities
"""

import logging
import time
from datetime import datetime, timedelta, timezone

from homeassistant.components.datetime import DateTimeEntity

from .device import TuyaLocalDevice
from .entity import TuyaLocalEntity
from .helpers.config import async_tuya_setup_platform
from .helpers.device_config import TuyaEntityConfig

_LOGGER = logging.getLogger(__name__)

EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)


async def async_setup_entry(hass, config_entry, async_add_entities):
    config = {**config_entry.data, **config_entry.options}
    await async_tuya_setup_platform(
        hass,
        async_add_entities,
        config,
        "datetime",
        TuyaLocalDateTime,
    )


class TuyaLocalDateTime(TuyaLocalEntity, DateTimeEntity):
    """Representation of a Tuya DateTime"""

    def __init__(self, device: TuyaLocalDevice, config: TuyaEntityConfig):
        """
        Initialise the datetime entity.
        Args:
            device (TuyaLocalDevice): the device API instance
            config (TuyaEntityConfig): the configuration for this entity
        """
        super().__init__()
        dps_map = self._init_begin(device, config)
        self._year_dps = dps_map.pop("year", None)
        self._month_dps = dps_map.pop("month", None)
        self._day_dps = dps_map.pop("day", None)
        self._hour_dps = dps_map.pop("hour", None)
        self._minute_dps = dps_map.pop("minute", None)
        self._second_dps = dps_map.pop("second", None)
        if (
            self._year_dps is None
            and self._month_dps is None
            and self._day_dps is None
            and self._hour_dps is None
            and self._minute_dps is None
            and self._second_dps is None
        ):
            raise AttributeError(
                f"{config.config_id} is missing an hour, minute or second dp"
            )
        self._init_end(dps_map)

    @property
    def native_value(self):
        """Return the current value of the time."""
        year = month = day = hours = minutes = seconds = None
        tz = timezone.utc
        if self._year_dps:
            year = self._year_dps.get_value(self._device)
            tz = time.now().astimezone().tzinfo
        if self._month_dps:
            month = self._month_dps.get_value(self._device)
        if self._day_dps:
            day = self._day_dps.get_value(self._device)
        if self._hour_dps:
            hours = self._hour_dps.get_value(self._device)
        if self._minute_dps:
            minutes = self._minute_dps.get_value(self._device)
        if self._second_dps:
            seconds = self._second_dps.get_value(self._device)
        if (
            year is None
            and month is None
            and day is None
            and hours is None
            and minutes is None
            and seconds is None
        ):
            return None
        year = year or 1970
        month = month or 1
        days = (day or 1) - 1
        hours = hours or 0
        minutes = minutes or 0
        seconds = seconds or 0
        delta = timedelta(
            days=int(days),
            hours=int(hours),
            minutes=int(minutes),
            seconds=int(seconds),
        )
        return datetime(year=year, month=month, day=1, tzinfo=tz) + delta

    async def async_set_value(self, value: datetime):
        """Set the datetime."""
        settings = {}
        # Use Local time if split into components
        if self._year_dps:
            tz = time.now().astimezone().tzinfo
            value = value.astimezone(tz)
        year = value.year
        month = value.month
        day = value.day
        hour = value.hour
        minute = value.minute
        second = value.second
        if self._year_dps:
            _LOGGER.info("%s setting year to %d", self.name, year)
            settings.update(
                self._year_dps.get_values_to_set(self._device, year, settings)
            )
            month = month + (year - 1970) * 12
        if self._month_dps:
            _LOGGER.info("%s setting month to %d", self.name, month)
            settings.update(
                self._month_dps.get_values_to_set(self._device, month, settings)
            )
        else:
            if self._year_dps is None:
                from_year = 1970
            else:
                from_year = value.year
            day = (
                day
                + (
                    datetime(value.year, value.month, 1) - datetime(from_year, 1, 1)
                ).days
                - 1
            )
        if self._day_dps:
            _LOGGER.info("%s setting day to %d", self.name, day)
            settings.update(
                self._day_dps.get_values_to_set(self._device, day, settings)
            )
        else:
            hour = hour + day * 24
        if self._hour_dps:
            _LOGGER.info("%s setting hour to %d", self.name, hour)
            settings.update(
                self._hour_dps.get_values_to_set(self._device, hour, settings)
            )
        else:
            minute = minute + hour * 60

        if self._minute_dps:
            _LOGGER.info("%s setting minute to %d", self.name, minute)
            settings.update(
                self._minute_dps.get_values_to_set(self._device, minute, settings)
            )
        else:
            second = second + minute * 60

        if self._second_dps:
            _LOGGER.info("%s setting second to %d", self.name, second)
            settings.update(
                self._second_dps.get_values_to_set(self._device, second, settings)
            )
        else:
            _LOGGER.debug(
                "%s: Discarding unused precision: %d seconds",
                self.name,
                second,
            )

        await self._device.async_set_properties(settings)
