"""Implement the auth feature from Hass.io for Add-ons."""
import logging
import os
from ipaddress import ip_address

import voluptuous as vol
from aiohttp import web
from aiohttp.web_exceptions import HTTPForbidden, HTTPNotFound

import homeassistant.helpers.config_validation as cv
from homeassistant.components.http import HomeAssistantView
from homeassistant.components.http.const import KEY_REAL_IP
from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.typing import HomeAssistantType

from .const import ATTR_ADDON, ATTR_PASSWORD, ATTR_USERNAME

_LOGGER = logging.getLogger(__name__)


SCHEMA_API_AUTH = vol.Schema({
    vol.Required(ATTR_USERNAME): cv.string,
    vol.Required(ATTR_PASSWORD): cv.string,
    vol.Required(ATTR_ADDON): cv.string,
}, extra=vol.ALLOW_EXTRA)


@callback
def async_setup_auth_view(hass: HomeAssistantType):
    """Auth setup."""
    hassio_auth = HassIOAuth(hass)
    hass.http.register_view(hassio_auth)


class HassIOAuth(HomeAssistantView):
    """Hass.io view to handle base part."""

    name = "api:hassio_auth"
    url = "/api/hassio_auth"

    def __init__(self, hass):
        """Initialize WebView."""
        self.hass = hass

    @RequestDataValidator(SCHEMA_API_AUTH)
    async def post(self, request, data):
        """Handle new discovery requests."""
        hassio_ip = os.environ['HASSIO'].split(':')[0]
        if request[KEY_REAL_IP] != ip_address(hassio_ip):
            _LOGGER.error(
                "Invalid auth request from %s", request[KEY_REAL_IP])
            raise HTTPForbidden()

        await self._check_login(data[ATTR_USERNAME], data[ATTR_PASSWORD])
        return web.Response(status=200)

    def _get_provider(self):
        """Return Homeassistant auth provider."""
        prv = self.hass.auth.get_auth_provider('homeassistant', None)
        if prv is not None:
            return prv

        _LOGGER.error("Can't find Home Assistant auth.")
        raise HTTPNotFound()

    async def _check_login(self, username, password):
        """Check User credentials."""
        provider = self._get_provider()

        try:
            await provider.async_validate_login(username, password)
        except HomeAssistantError:
            raise HTTPForbidden() from None