"""
Pearson Service Insight's Divvy API Module
This module contains a class with methods to interact with the Divvy API.
"""

import json
import logging
import os
from itertools import chain
from typing import Optional

import requests

from divvy import get_logger, log_it


DIVVY_V2_API_URL = os.environ.get(
    "DIVVY_V2_API_URL", "https://pearsonedu.customer.divvycloud.com/v2"
)


class Divvy:

    def __init__(
        self,
        api_key: str,
        http_session: Optional[requests.Session] = None,
        logger: Optional[logging.Logger] = None,
    ):
        self._http_session = http_session or requests.Session()
        self._logger = logger or get_logger()
        self._headers = {
            "Accept": "application/json",
            "Api-Key": api_key,
            "Content-Type": "application/json",
        }

    @log_it
    def get_compliance_scores(self, data: dict) -> dict:
        """Return all results from the divy endpoint as json

        Parameters
        ----------
        data : dict
            ex:
                data = {"pack_id":24,"organization_service_ids":[9320],"pack_source":"custom","days":3,"badges":[],"badge_filter_operator":"OR","start_date":"2021-09-30","end_date":"2021-10-06"}

            organization_service_ids? 9320 = Governator, these need to be mapped to our accounts as they are Divvy ids.  Will be addressed in future ticket.

        Returns
        -------
            ...large json
            {
                "severity_data": {
                    "10/07/2021": {
                        "aws_count": 1,
                        "gcp_count": 0,
                        "azure_count": 0,
                        "alibaba_count": 0,
                        "kubernetes_count": 0,
                        "oracle_count": 0,
                        "total_findings": 166,
                        "resources_in_scope": 1289,
                        "minor": 5,
                        "moderate": 3,
                        "major": 105,
                        "severe": 50,
                        "critical": 3,
                        "total_count": 1
                    }
                },
                "insights_by_severity": {
                    "minor": 2,
                    "moderate": 6,
                    "major": 13,
                    "severe": 10,
                    "critical": 6
                },
                "exemption_counts": {
                    "Minor": 0,
                    "Moderate": 0,
                    "Major": 0,
                    "Severe": 0,
                    "Critical": 0
                },
                "pack_data": {
                    "09/30/2021": {
                        "backoffice_count": 31,
                        "custom_count": 7,
                        "exemption_count": 0
                    }
                },
                "snapshot": {
                    "compliance_score": 0.8712179984484096,
                    "severity_counts": {
                        "minor": {
                            "severity_rank": 1,
                            "findings": 5,
                            "insights": 2,
                            "exemptions": 0,
                            "diff_percent": 0
                        },
                        "moderate": {
                            "severity_rank": 2,
                            "findings": 3,
                            "insights": 6,
                            "exemptions": 0,
                            "diff_percent": 0
                        },
                        "major": {
                            "severity_rank": 3,
                            "findings": 105,
                            "insights": 13,
                            "exemptions": 0,
                            "diff_percent": -0.018691588785046728
                        },
                        "severe": {
                            "severity_rank": 4,
                            "findings": 50,
                            "insights": 10,
                            "exemptions": 0,
                            "diff_percent": 0
                        },
                        "critical": {
                            "severity_rank": 5,
                            "findings": 3,
                            "insights": 6,
                            "exemptions": 0,
                            "diff_percent": 0
                        }
                    },
                    "total_findings": 166,
                    "total_resources": 1289,
                    "total_exemptions": 0,
                    "date": "10/07/2021"
                },
                "trends_over_time": {
                    "compliance_scores": [
                        {
                            "date": "09/30/2021",
                            "total": 0.8608964451313755,
                            "minor": 0.7727272727272727,
                            "moderate": 0.9754098360655737,
                            "major": 0.746268656716418,
                            "severe": 0.8538011695906432,
                            "critical": 0.9911504424778761
                        }],
                    "findings_by_severity": {
                        "minor": [
                            {
                                "date": "09/30/2021",
                                "value": 5
                            }],
                        "moderate": [
                            {
                                "date": "09/30/2021",
                                "value": 3
                            }],
                        "major": [
                            {
                                "date": "09/30/2021",
                                "value": 119
                            }],
                        "severe": [
                            {
                                "date": "09/30/2021",
                                "value": 50
                            }],
                        "critical": [
                            {
                                "date": "09/30/2021",
                                "value": 3
                            }]
                    },
                    "insight_counts": {
                        "backoffice": [
                            {
                                "date": "09/30/2021",
                                "value": 31
                            }],
                        "custom": [
                            {
                                "date": "09/30/2021",
                                "value": 7
                            }],
                        "exemptions": [
                            {
                                "date": "09/30/2021",
                                "value": 0
                            }]
                    },
                    "cloud_counts": {
                        "AWS": [
                            {
                                "date": "09/30/2021",
                                "value": 1
                            }],
                        "GCE": [
                            {
                                "date": "09/30/2021",
                                "value": 0
                            }],
                        "AZURE_ARM": [
                            {
                                "date": "09/30/2021",
                                "value": 0
                            }],
                        "ALICLOUD": [
                            {
                                "date": "09/30/2021",
                                "value": 0
                            }],
                        "K8S": [
                            {
                                "date": "09/30/2021",
                                "value": 0
                            }],
                        "OCI": [
                            {
                                "date": "09/30/2021",
                                "value": 0
                            }]
                    }
                }
            }
        """
        url = DIVVY_V2_API_URL + "/compliance/system/report"
        response = self._http_session.post(url, headers=self._headers, data=json.dumps(data))
        self._logger.debug(response.request.headers)
        self._logger.info(f"{response.request.method} {response.request.url}")
        response.raise_for_status()
        return response.json()

    @log_it
    def get_cloud_listing(self, data: dict):
        """Returns
            data : dict
                ex:
                    data = {"limit":25,"offset":0,"empty_badges":False,"order_by":"name","badges":[],"badge_filter_operator":"OR","filters":[]}
        Returns:
            {   'clouds': [   {   'account_id': 'cogmed-216121',
                      'badge_count': 1,
                      'cloud_organization_id': '443334724975',
                      'cloud_type_id': 'GCE',
                      'creation_time': '2020-12-07 20:58:33',
                      'disabled_resource_types': [   'sharedfilesystem',
                                                     'serviceencryptionkey',
                                                     'mapreducecluster',
                                                     'dbinstance',
                                                     'database',
                                                     'dbsnapshot',
                                                     'notificationtopic',
                                                     'notificationsubscription',
                                                     'servicecost',
                                                     'instance',
                                                     'networkpeer',
                                                     'privatenetwork',
                                                     'privatesubnet',
                                                     'publicip',
                                                     'loadbalancer',
                                                     'networkinterface',
                                                     'resourceaccesslist',
                                                     'servicecertificate',
                                                     'snapshot',
                                                     'autoscalinggroup',
                                                     'privateimage',
                                                     'servicelimit',
                                                     'serviceuser',
                                                     'servicegroup',
                                                     'servicerole',
                                                     'servicepolicy',
                                                     'serviceaccesskey',
                                                     'servicemanagedpolicy',
                                                     'bigdatainstance',
                                                     'distributedtablecluster',
                                                     'serverlessfunction',
                                                     'spanner',
                                                     'spannerdatabase',
                                                     'dnszone',
                                                     'containercluster',
                                                     'mlinstance',
                                                     'mcinstance',
                                                     'identityprovider'],
                      'event_driven_harvest_role': 'idle',
                      'group_resource_id': 'divvyorganizationservice:7605',
                      'id': 7605,
                      'last_refreshed': '2021-10-13 12:08:45',
                      'name': ' cogmed-216121',
                      'resource_count': 47,
                      'resource_id': 'divvyorganizationservice:7605',
                      'role_arn': 'divvycloud-gcp-integration@masterserviceaccount.iam.gserviceaccount.com',
                      'status': 'DEFAULT',
                      'strategy_id': 3}]
            }
        """
        url = DIVVY_V2_API_URL + "/public/clouds/list"
        response = self._http_session.post(url, headers=self._headers, data=json.dumps(data))
        self._logger.debug(response.request.headers)
        self._logger.info(f"{response.request.method} {response.request.url}")
        response.raise_for_status()
        return response.json()

    @log_it
    def get_resources_with_tags(self, data: dict) -> dict:
        """Return all results from the divvy endpoint as json

        Parameters
        ----------
        data : dict
            ex:
                data = {
                            "tag_keys": ["t_AppID"],
                            "resource_types": [],
                            "organization_services": [],
                            "options": {"limit": 25, "offset": 0,
                                        "order_by": "name", "filters": []},
                            "contains_all": True,
                            "missing_all": False,
                            "case_insensitive": False,
                            "search_string": ""
                    }

        Returns
        -------
            ...large json
            {
        "resources": [{
                "resource_id": "publicip:8726:us-east-1:3.95.15.49:",
                "provider_id": "3.95.15.49",
                "name": "",
                "region_name": "us-east-1",
                "resource_type": "publicip",
                "daily_cost": 0.12,
                "account": "ate-io-product116",
                "account_id": "172061886000",
                "cloud_type_id": "AWS",
                "t_AppID": null
        }, {
                "resource_id": "publicip:8875:us-east-1:34.226.123.250:",
                "provider_id": "34.226.123.250",
                "name": "",
                "region_name": "us-east-1",
                "resource_type": "publicip",
                "daily_cost": 0,
                "account": "Pearson AI_Cloud_Admin",
                "account_id": "012597783113",
                "cloud_type_id": "AWS",
                "t_AppID": null
        }],
        "total_count": 57799,
        "next_cursor": "eyJvZmZzZXQiOiAyNSwgImNoZWNrc3VtIjogIjk4N
        2Q2YTNmYTBhMTU0NmUyMDRiMWQzNmNhMTE5ZGE1MTdiMGE0ZGNkOTA4NTliNGY4OWQ0NWQ4MzY1YTAyODcifQ=="
        }
        """
        cursor = None
        resources = []
        response = {}
        data["cursor"] = cursor
        url = DIVVY_V2_API_URL + "/public/resources/tags/search"
        while True:
            print("===Processing Batch===")
            response_batch = self._http_session.post(
                url, headers=self._headers, data=json.dumps(data)
            )
            self._logger.debug(response_batch.request.headers)
            self._logger.info(
                f"{response_batch.request.method} \
                        {response_batch.request.url}"
            )
            response_batch.raise_for_status()
            response_batch_json = response_batch.json()
            resources.append(response_batch_json.get("resources", []))
            cursor = response_batch_json.get("next_cursor", None)
            data["cursor"] = cursor
            if not cursor:
                response["total_count"] = response_batch_json.get("total_count", None)
                print("Processing Complete")
                break
        resources_flat = list(chain(*resources))
        response["resources"] = resources_flat
        return response

    def __repr__(self) -> str:
        """Return a string representation of the object"""
        return f"Divvy()"
