from typing import Tuple

import boto3
from flask import current_app

from app import app
from app.alarms import get_or_create_alarm
from app.brm.brn import BRN
from app.extensions import db
from app.models.mirrors import Proxy
from app.models.alarms import AlarmState
from app.terraform import BaseAutomation


def _cloudfront_quota() -> None:
    # It would be nice to learn this from the Service Quotas API, however
    # at the time of writing this comment, the current value for this quota
    # is not available from the API. It just doesn't return anything.
    max_count = int(current_app.config.get('AWS_CLOUDFRONT_MAX_DISTRIBUTIONS', 200))
    deployed_count = len(Proxy.query.filter(
        Proxy.destroyed.is_(None)).all())
    message = f"{deployed_count} distributions deployed of {max_count} quota"
    alarm = get_or_create_alarm(
        BRN(
            group_id=0,
            product="mirror",
            provider="cloudfront",
            resource_type="quota",
            resource_id="distributions"
        ),
        "quota-usage"
    )
    if deployed_count > max_count * 0.9:
        alarm.update_state(AlarmState.CRITICAL, message)
    elif deployed_count > max_count * 0.75:
        alarm.update_state(AlarmState.WARNING, message)
    else:
        alarm.update_state(AlarmState.OK, message)


def _proxy_alarms() -> None:
    cloudwatch = boto3.client('cloudwatch',
                              aws_access_key_id=app.config['AWS_ACCESS_KEY'],
                              aws_secret_access_key=app.config['AWS_SECRET_KEY'],
                              region_name='us-east-2')
    dist_paginator = cloudwatch.get_paginator('describe_alarms')
    page_iterator = dist_paginator.paginate(AlarmNamePrefix="bandwidth-out-high-")
    for page in page_iterator:
        for cw_alarm in page['MetricAlarms']:
            dist_id = cw_alarm["AlarmName"][len("bandwidth-out-high-"):]
            proxy = Proxy.query.filter(Proxy.slug == dist_id).first()
            if proxy is None:
                print("Skipping unknown proxy " + dist_id)
                continue
            alarm = get_or_create_alarm(proxy.brn, "bandwidth-out-high")
            if cw_alarm['StateValue'] == "OK":
                alarm.update_state(AlarmState.OK, "CloudWatch alarm OK")
            elif cw_alarm['StateValue'] == "ALARM":
                alarm.update_state(AlarmState.CRITICAL, "CloudWatch alarm ALARM")
            else:
                alarm.update_state(AlarmState.UNKNOWN, f"CloudWatch alarm {cw_alarm['StateValue']}")


class AlarmProxyCloudfrontAutomation(BaseAutomation):
    short_name = "monitor_proxy_cloudfront"
    description = "Import alarms for AWS CloudFront proxies"

    def automate(self, full: bool = False) -> Tuple[bool, str]:
        _proxy_alarms()
        _cloudfront_quota()
        db.session.commit()
        return True, ""
