from django.conf import settings
from rest_framework import status
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView

from apps.grafana_plugin.helpers import GrafanaAPIClient
from apps.user_management.models.organization import Organization
from apps.user_management.sync import sync_organization
from common.api_helpers.mixins import GrafanaHeadersMixin


class SelfHostedInstallView(GrafanaHeadersMixin, APIView):
    def post(self, _request: Request) -> Response:
        """
        We've already validated that settings.GRAFANA_API_URL is set (in apps.grafana_plugin.GrafanaPluginConfig)
        The user is now trying to finish plugin installation. We'll take the Grafana API url that they specified +
        the token that we are provided and first verify them. If all is good, upsert the organization in the database,
        and provision the plugin.
        """
        stack_id = settings.SELF_HOSTED_SETTINGS["STACK_ID"]
        org_id = settings.SELF_HOSTED_SETTINGS["ORG_ID"]
        grafana_url = settings.SELF_HOSTED_SETTINGS["GRAFANA_API_URL"]
        grafana_api_token = self.instance_context["grafana_token"]

        provisioning_info = {"error": None}

        if settings.LICENSE != settings.OPEN_SOURCE_LICENSE_NAME:
            provisioning_info["error"] = "License type not authorized"
            return Response(status=status.HTTP_403_FORBIDDEN)

        grafana_api_client = GrafanaAPIClient(api_url=grafana_url, api_token=grafana_api_token)
        _, client_status = grafana_api_client.check_token()
        status_code = client_status["status_code"]

        if status_code == status.HTTP_404_NOT_FOUND:
            provisioning_info["error"] = f"Unable to connect to the specified Grafana API - {grafana_url}"
            return Response(data=provisioning_info, status=status.HTTP_400_BAD_REQUEST)
        elif status_code in [status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN]:
            provisioning_info[
                "error"
            ] = f"You are not authorized to communicate with the specified Grafana API - {grafana_url}"
            return Response(data=provisioning_info, status=status.HTTP_400_BAD_REQUEST)

        organization = Organization.objects.filter(stack_id=stack_id, org_id=org_id).first()
        rbac_is_enabled, _ = grafana_api_client.is_rbac_enabled_for_organization()

        if organization:
            organization.revoke_plugin()
            organization.grafana_url = grafana_url
            organization.api_token = grafana_api_token
            organization.is_rbac_permissions_enabled = rbac_is_enabled
            organization.save(update_fields=["grafana_url", "api_token", "is_rbac_permissions_enabled"])
        else:
            organization = Organization.objects.create(
                stack_id=stack_id,
                stack_slug=settings.SELF_HOSTED_SETTINGS["STACK_SLUG"],
                org_id=org_id,
                org_slug=settings.SELF_HOSTED_SETTINGS["ORG_SLUG"],
                org_title=settings.SELF_HOSTED_SETTINGS["ORG_TITLE"],
                region_slug=settings.SELF_HOSTED_SETTINGS["REGION_SLUG"],
                cluster_slug=settings.SELF_HOSTED_SETTINGS["CLUSTER_SLUG"],
                grafana_url=grafana_url,
                api_token=grafana_api_token,
                is_rbac_permissions_enabled=rbac_is_enabled,
            )

        sync_organization(organization)
        provisioning_info.update(organization.provision_plugin())

        return Response(data=provisioning_info, status=status.HTTP_201_CREATED)
