"""Services for the bosch_alarm integration."""

from __future__ import annotations

import asyncio
import datetime as dt
from typing import Any

import voluptuous as vol

from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import ATTR_CONFIG_ENTRY_ID
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import config_validation as cv
from homeassistant.util import dt as dt_util

from .const import ATTR_DATETIME, DOMAIN, SERVICE_SET_DATE_TIME
from .types import BoschAlarmConfigEntry


def validate_datetime(value: Any) -> dt.datetime:
    """Validate that a provided datetime is supported on a bosch alarm panel."""
    date_val = cv.datetime(value)
    if date_val.year < 2010:
        raise vol.RangeInvalid("datetime must be after 2009")

    if date_val.year > 2037:
        raise vol.RangeInvalid("datetime must be before 2038")

    return date_val


SET_DATE_TIME_SCHEMA = vol.Schema(
    {
        vol.Required(ATTR_CONFIG_ENTRY_ID): cv.string,
        vol.Optional(ATTR_DATETIME): validate_datetime,
    }
)


async def async_set_panel_date(call: ServiceCall) -> None:
    """Set the date and time on a bosch alarm panel."""
    config_entry: BoschAlarmConfigEntry | None
    value: dt.datetime = call.data.get(ATTR_DATETIME, dt_util.now())
    entry_id = call.data[ATTR_CONFIG_ENTRY_ID]
    if not (config_entry := call.hass.config_entries.async_get_entry(entry_id)):
        raise ServiceValidationError(
            translation_domain=DOMAIN,
            translation_key="integration_not_found",
            translation_placeholders={"target": entry_id},
        )
    if config_entry.state is not ConfigEntryState.LOADED:
        raise HomeAssistantError(
            translation_domain=DOMAIN,
            translation_key="not_loaded",
            translation_placeholders={"target": config_entry.title},
        )
    panel = config_entry.runtime_data
    try:
        await panel.set_panel_date(value)
    except asyncio.InvalidStateError as err:
        raise HomeAssistantError(
            translation_domain=DOMAIN,
            translation_key="connection_error",
            translation_placeholders={"target": config_entry.title},
        ) from err


@callback
def async_setup_services(hass: HomeAssistant) -> None:
    """Set up the services for the bosch alarm integration."""

    hass.services.async_register(
        DOMAIN,
        SERVICE_SET_DATE_TIME,
        async_set_panel_date,
        schema=SET_DATE_TIME_SCHEMA,
    )
