import json
import logging
import os
import urllib.request
from typing import Optional
from urllib.error import (
    HTTPError,
    URLError,
)

from edpconfigprovider import ConfigProvider
from edpconfigprovider.exceptions import NoConfigurationException

logger = logging.getLogger(__name__)

# AppConfig agent layer port environment variable
_DEFAULT_APP_CONFIG_AGENT_HOST = os.environ.get("AWS_APPCONFIG_AGENT_HOST", "localhost")
_DEFAULT_APP_CONFIG_AGENT_PORT = os.environ.get("AWS_APPCONFIG_EXTENSION_HTTP_PORT", "2772")

class AwsAppconfigAgentProvider(ConfigProvider):
    def __init__(
        self,
        application_name: str,
        profile_name: str,
        environment_name: str,
        port: Optional[int] = None,
    ):
        self.application_name = application_name
        self.profile_name = profile_name
        self.environment_name = environment_name
        self.port = port if port is not None else _DEFAULT_APP_CONFIG_AGENT_PORT

    def get_configuration(self) -> dict:
        try:
            url = f"http://{_DEFAULT_APP_CONFIG_AGENT_HOST}:{self.port}/applications/{self.application_name}/environments/{self.environment_name}/configurations/{self.profile_name}"  # noqa
            return json.loads(urllib.request.urlopen(url).read())
        except (HTTPError, URLError):
            logger.exception("Failed to fetch configuration from AWS AppConfig")

            config_name = f"{self.application_name}/{self.environment_name}/{self.profile_name}"
            raise NoConfigurationException(configuration_name=config_name)

    def cache_key(self) -> str:
        return f"{self.application_name}:{self.environment_name}:{self.profile_name}"
