"""Services for the Fully Kiosk Browser integration."""
from __future__ import annotations

import voluptuous as vol

from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.const import ATTR_DEVICE_ID
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import HomeAssistantError
import homeassistant.helpers.config_validation as cv
import homeassistant.helpers.device_registry as dr

from .const import (
    ATTR_APPLICATION,
    ATTR_KEY,
    ATTR_URL,
    ATTR_VALUE,
    DOMAIN,
    SERVICE_LOAD_URL,
    SERVICE_SET_CONFIG,
    SERVICE_START_APPLICATION,
)
from .coordinator import FullyKioskDataUpdateCoordinator


async def async_setup_services(hass: HomeAssistant) -> None:
    """Set up the services for the Fully Kiosk Browser integration."""

    async def collect_coordinators(
        device_ids: list[str],
    ) -> list[FullyKioskDataUpdateCoordinator]:
        config_entries = list[ConfigEntry]()
        registry = dr.async_get(hass)
        for target in device_ids:
            device = registry.async_get(target)
            if device:
                device_entries = list[ConfigEntry]()
                for entry_id in device.config_entries:
                    entry = hass.config_entries.async_get_entry(entry_id)
                    if entry and entry.domain == DOMAIN:
                        device_entries.append(entry)
                if not device_entries:
                    raise HomeAssistantError(
                        f"Device '{target}' is not a {DOMAIN} device"
                    )
                config_entries.extend(device_entries)
            else:
                raise HomeAssistantError(
                    f"Device '{target}' not found in device registry"
                )
        coordinators = list[FullyKioskDataUpdateCoordinator]()
        for config_entry in config_entries:
            if config_entry.state != ConfigEntryState.LOADED:
                raise HomeAssistantError(f"{config_entry.title} is not loaded")
            coordinators.append(hass.data[DOMAIN][config_entry.entry_id])
        return coordinators

    async def async_load_url(call: ServiceCall) -> None:
        """Load a URL on the Fully Kiosk Browser."""
        for coordinator in await collect_coordinators(call.data[ATTR_DEVICE_ID]):
            await coordinator.fully.loadUrl(call.data[ATTR_URL])

    async def async_start_app(call: ServiceCall) -> None:
        """Start an app on the device."""
        for coordinator in await collect_coordinators(call.data[ATTR_DEVICE_ID]):
            await coordinator.fully.startApplication(call.data[ATTR_APPLICATION])

    async def async_set_config(call: ServiceCall) -> None:
        """Set a Fully Kiosk Browser config value on the device."""
        for coordinator in await collect_coordinators(call.data[ATTR_DEVICE_ID]):
            # Fully API has different methods for setting string and bool values.
            # check if call.data[ATTR_VALUE] is a bool
            if isinstance(call.data[ATTR_VALUE], bool) or call.data[
                ATTR_VALUE
            ].lower() in ("true", "false"):
                await coordinator.fully.setConfigurationBool(
                    call.data[ATTR_KEY], call.data[ATTR_VALUE]
                )
            else:
                await coordinator.fully.setConfigurationString(
                    call.data[ATTR_KEY], call.data[ATTR_VALUE]
                )

    # Register all the above services
    service_mapping = [
        (async_load_url, SERVICE_LOAD_URL, ATTR_URL),
        (async_start_app, SERVICE_START_APPLICATION, ATTR_APPLICATION),
    ]
    for service_handler, service_name, attrib in service_mapping:
        hass.services.async_register(
            DOMAIN,
            service_name,
            service_handler,
            schema=vol.Schema(
                vol.All(
                    {
                        vol.Required(ATTR_DEVICE_ID): cv.ensure_list,
                        vol.Required(attrib): cv.string,
                    }
                )
            ),
        )

    hass.services.async_register(
        DOMAIN,
        SERVICE_SET_CONFIG,
        async_set_config,
        schema=vol.Schema(
            vol.All(
                {
                    vol.Required(ATTR_DEVICE_ID): cv.ensure_list,
                    vol.Required(ATTR_KEY): cv.string,
                    vol.Required(ATTR_VALUE): vol.Any(str, bool),
                }
            )
        ),
    )
