import json
import os
from typing import NamedTuple

from starlette_proxy_router.exceptions import HostNotFoundError
from starlette_proxy_router.types import AuthType, PathURL, ProxyPathURL
from starlette_proxy_router.validate import ConfigValidate, HostValidate, MethodHTTP


class EndpointArgs(NamedTuple):
    path: PathURL
    target: ProxyPathURL
    method: MethodHTTP
    host: str
    service_name: str
    is_auth: bool = False
    timeout: int | None = None
    auth_type: AuthType | None = None
    auth_fields: list[str] | None = None


class Parser:
    __slots__ = ("_path_file",)

    def __init__(self, path_file: str) -> None:
        self._path_file = path_file

    def parse_config(self) -> list[EndpointArgs]:
        with open(self._path_file) as file:
            content = json.loads(file.read())
            data = self._validate_config(content)
            return self._parse(data)

    def _validate_config(self, data: dict) -> ConfigValidate:
        return ConfigValidate.model_validate(data)

    def _validate_and_get_host(self, service_name: str) -> str:
        host = os.environ.get(service_name)
        if host:
            host_validate = HostValidate.model_validate({'host': host})
            return str(host_validate.host)
        raise HostNotFoundError(f"Host for service '{service_name}' not found in env")

    def _parse(self, config_validate: ConfigValidate) -> list[EndpointArgs]:
        args_endpoints = []
        for service in config_validate.services:
            for endpoint in service.endpoints:
                args = EndpointArgs(
                    path=endpoint.path,
                    target=endpoint.target if endpoint.target else endpoint.path,
                    method=endpoint.method or MethodHTTP.GET,
                    is_auth=(
                        endpoint.is_auth
                        if endpoint.is_auth is not None
                        else config_validate.authenfication.default_on_endpoint
                    ),
                    auth_type=config_validate.authenfication.default_type,
                    auth_fields=config_validate.authenfication.fields,
                    service_name=service.service,
                    host=self._validate_and_get_host(service.service),
                    timeout=endpoint.timeout,
                )
                args_endpoints.append(args)
        return args_endpoints
