import traceback

from typing import Union, Optional

from pydantic import BaseModel

from fastapi import HTTPException

from ehelply_python_sdk.services.access.auth_rules import AuthRule, AuthException
from ehelply_python_sdk.services.access.sdk import AuthModel

from ehelply_microservice_library.integrations.monitor import Monitor


class CloudParticipant(BaseModel):
    active_participant: str
    project_uuid: str
    is_privileged: bool = False
    entity_identifier: Optional[str] = None


async def ehelply_cloud_access(
        auth: AuthModel,
        node: str,
        service_target: str,
        monitor: Monitor,
        ignore_project_enabled=False,
        ignore_spend_limits=False,
        exception_if_unauthorized=True,
        exception_if_spend_maxed=True,
        exception_if_project_not_enabled=True,
) -> Union[bool, CloudParticipant]:
    """

    Args:
        auth:
        node:
        service_target:
        monitor: Send in the monitor integration and project max spend will be checked automatically
        exception_if_unauthorized:
        exception_if_spend_maxed:

    Returns:

    """
    # Admin or M2M access
    try:
        await AuthRule(
            auth,
            exception_if_unauthorized=True
        ).participant_has_node_on_target(
            node=node,
            target_identifier=service_target,
            partition="ehelply-resources"
        ).verify()

        return CloudParticipant(
            is_privileged=True,
            active_participant=auth.active_participant_uuid,
            project_uuid=auth.project_uuid,
            entity_identifier=auth.entity_identifier
        )
    except (AuthException, HTTPException):
        pass
    except Exception as e:
        traceback.print_exc()
        raise HTTPException(
            status_code=500,
            detail="Ruh Roh, something has gone terribly wrong - Denied by eHelply."
        )

    spend_maxed: bool = False
    project_not_enabled: bool = False

    # Regular eHelply Cloud access
    try:
        await AuthRule(
            auth,
            exception_if_unauthorized=True
        ).participant_has_node_on_target(
            node=node,
            target_identifier=auth.project_uuid,
            partition="ehelply-cloud"
        ).customentity_has_node_on_target(
            node=node,
            target_identifier=service_target,
            partition="ehelply-cloud",
            entity_identifier=auth.project_uuid
        ).verify()

        project = await monitor.get_project(project_uuid=auth.project_uuid)

        if not ignore_project_enabled and project.status != "enabled":
            project_not_enabled = True
            raise AuthException("Project is not enabled")

        if not ignore_spend_limits and project.is_spend_maxed:
            spend_maxed = True
            raise AuthException("Spend is maxed")

        return CloudParticipant(
            is_privileged=False,
            active_participant=auth.active_participant_uuid,
            project_uuid=auth.project_uuid,
            entity_identifier=auth.entity_identifier
        )
    except (AuthException, HTTPException):
        pass
    except Exception as e:
        traceback.print_exc()
        raise HTTPException(
            status_code=500,
            detail="Ruh Roh, something has gone terribly wrong - Denied by eHelply."
        )

    if spend_maxed and exception_if_spend_maxed:
        raise HTTPException(
            status_code=400,
            detail="Project spend is maxed - Denied by eHelply. Increase max spend to complete this request."
        )
    elif spend_maxed:
        return False

    if project_not_enabled and exception_if_project_not_enabled:
        raise HTTPException(
            status_code=400,
            detail="Project is not enabled - Denied by eHelply. The project may be awaiting approval or disabled."
        )
    elif project_not_enabled:
        return False

    if exception_if_unauthorized:
        raise HTTPException(status_code=403, detail="Unauthorized - Denied by eHelply")
    else:
        return False

    #
    # return AuthRule(
    #     auth,
    #     AuthRule(auth).participant_has_node_on_target(
    #         node=node,
    #         target_identifier=service_target,
    #         partition="ehelply-resources"
    #     ),
    #     AuthRule(auth).participant_has_node_on_target(
    #         node=node,
    #         target_identifier=auth.project_uuid,
    #         partition="ehelply-cloud"
    #     ).customentity_has_node_on_target(
    #         node=node,
    #         target_identifier=service_target,
    #         partition="ehelply-cloud",
    #         entity_identifier=auth.project_uuid
    #     ),
    #     exception_if_unauthorized=exception_if_unauthorized
    # ).verify()
