import logging

import requests as rest_requests

from .._BaseCedarAuthorizationService import BaseCedarAuthorizationService
from ..dto import CedarUidEntity

_DEFAULT_LOGGER = logging.getLogger("edpauthorization.service.impl.cedar.cedarapi.CedarApiAuthorizationServiceImpl")


class CedarApiAuthorizationServiceImpl(BaseCedarAuthorizationService):
    def __init__(
        self,
        cedar_service_url: str,
        schema_namespace: str | None = None,
        use_batch: bool = False,
    ):
        super().__init__(schema_namespace=schema_namespace)
        self.cedar_service_url = cedar_service_url
        self.use_batch = use_batch

    def _call_is_authorized(self, request: dict, entities: list[CedarUidEntity]) -> bool:
        url = f"{self.cedar_service_url}/is_authorized"

        payload = self.get_encoded_json(
            {
                "principal": request["principal"],
                "action": request["action"],
                "resource": request["resource"],
                "context": request["context"],
                "entities": entities,
            }
        )

        _DEFAULT_LOGGER.debug("Authorization request: %s", payload)
        response = rest_requests.request(
            method="POST",
            url=url,
            headers={
                "Content-Type": "application/json",
            },
            data=payload,
        )

        if response.status_code != rest_requests.codes.ok:
            response.raise_for_status()

        response_data = response.json()

        allow = response_data.get("decision") == "Allow"
        if not allow:
            _DEFAULT_LOGGER.error("is_authorized request: %s", payload)
            _DEFAULT_LOGGER.error("is_authorized response: %s", response_data)

        return allow

    def _call_is_authorized_batch(self, requests: list[dict], entities: list[CedarUidEntity]) -> bool:
        if self.use_batch:
            raise NotImplementedError("Not Implemented")

        for request in requests:
            if not self._call_is_authorized(request, entities):
                return False

        return True
