"""Camera that loads a picture from a local file."""

import logging
import mimetypes
from typing import override

import voluptuous as vol

from homeassistant.components.camera import Camera
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_FILE_PATH, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .const import SERVICE_UPDATE_FILE_PATH
from .util import check_file_path_access

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(
    hass: HomeAssistant,
    entry: ConfigEntry,
    async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
    """Set up the Camera for local file from a config entry."""

    platform = entity_platform.async_get_current_platform()
    platform.async_register_entity_service(
        SERVICE_UPDATE_FILE_PATH,
        {
            vol.Required(CONF_FILE_PATH): cv.string,
        },
        "update_file_path",
    )

    async_add_entities(
        [
            LocalFile(
                entry.options[CONF_NAME],
                entry.options[CONF_FILE_PATH],
                entry.entry_id,
            )
        ]
    )


class LocalFile(Camera):
    """Representation of a local file camera."""

    def __init__(self, name: str, file_path: str, unique_id: str) -> None:
        """Initialize Local File Camera component."""
        super().__init__()
        self._attr_name = name
        self._attr_unique_id = unique_id
        self._file_path = file_path
        # Set content type of local file
        content, _ = mimetypes.guess_type(file_path)
        if content is not None:
            self.content_type = content

    @override
    def camera_image(
        self, width: int | None = None, height: int | None = None
    ) -> bytes | None:
        """Return image response."""
        try:
            with open(self._file_path, "rb") as file:
                return file.read()
        # pylint: disable-next=home-assistant-action-swallowed-exception
        except FileNotFoundError:
            _LOGGER.warning(
                "Could not read camera %s image from file: %s",
                self.name,
                self._file_path,
            )
        return None

    async def update_file_path(self, file_path: str) -> None:
        """Update the file_path."""
        if not await self.hass.async_add_executor_job(
            check_file_path_access, file_path
        ):
            raise ServiceValidationError(f"Path {file_path} is not accessible")
        self._file_path = file_path
        self.schedule_update_ha_state()

    @property
    @override
    def extra_state_attributes(self) -> dict[str, str]:
        """Return the camera state attributes."""
        return {"file_path": self._file_path}
