from typing import Optional, Any

from app.extensions import db
from app.models.mirrors import Proxy
from app.terraform.proxy import ProxyAutomation


class ProxyAzureCdnAutomation(ProxyAutomation):
    short_name = "proxy_azure_cdn"
    description = "Deploy proxies to Azure CDN"
    provider = "azure_cdn"
    subgroup_members_max = 25
    parallelism = 1
    cloud_name = "azure"

    template_parameters = [
        "azure_resource_group_name",
        "azure_storage_account_name",
        "azure_location",
        "azure_client_id",
        "azure_client_secret",
        "azure_subscription_id",
        "azure_tenant_id",
        "smart_zone"
    ]

    template = """
    terraform {
      {{ backend_config }}
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "=2.99.0"
        }
      }
    }

    provider "azurerm" {
      features {}
      client_id = "{{ azure_client_id }}"
      client_secret = "{{ azure_client_secret }}"
      subscription_id = "{{ azure_subscription_id }}"
      tenant_id = "{{ azure_tenant_id }}"
      skip_provider_registration = true
    }

    data "azurerm_resource_group" "this" {
      name = "{{ azure_resource_group_name }}"
    }

    resource "azurerm_storage_account" "this" {
      name                     = "{{ azure_storage_account_name }}"
      resource_group_name      = data.azurerm_resource_group.this.name
      location                 = "{{ azure_location }}"
      account_tier             = "Standard"
      account_replication_type = "RAGRS"
    }

    {% for group in groups %}
    module "label_{{ group.id }}" {
      source  = "cloudposse/label/null"
      version = "0.25.0"
      namespace = "{{ global_namespace }}"
      tenant = "{{ group.group_name }}"
      label_order = ["namespace", "tenant", "name", "attributes"]
    }

    {% for subgroup in subgroups[group.id] %}
    resource "azurerm_cdn_profile" "profile_{{ group.id }}_{{ subgroup }}" {
      name                = "${module.label_{{ group.id }}.id}-sub{{ subgroup }}"
      location            = "{{ azure_location }}"
      resource_group_name = data.azurerm_resource_group.this.name
      sku                 = "Standard_Microsoft"
      tags                = module.label_{{ group.id }}.tags
    }

    resource "azurerm_monitor_diagnostic_setting" "profile_diagnostic_{{ group.id }}_{{ subgroup }}" {
      name               = "cdn-diagnostics"
      target_resource_id = azurerm_cdn_profile.profile_{{ group.id }}_{{ subgroup }}.id
      storage_account_id = azurerm_storage_account.this.id

      log {
        category = "AzureCDNAccessLog"
        enabled  = true

        retention_policy {
          enabled = true
          days = 90
        }
      }

      metric {
        category = "AllMetrics"
        enabled  = true

        retention_policy {
          enabled = true
          days = 90
        }
      }
    }

    resource "azurerm_monitor_metric_alert" "response_alert_{{ group.id }}_{{ subgroup }}" {
      name                = "bandwidth-out-high-${module.label_{{ group.id }}.id}-sub{{ subgroup }}"
      resource_group_name = data.azurerm_resource_group.this.name
      scopes              = [azurerm_cdn_profile.profile_{{ group.id }}_{{ subgroup }}.id]
      description         = "Action will be triggered when response size is too high."

      criteria {
        metric_namespace = "Microsoft.Cdn/profiles"
        metric_name      = "ResponseSize"
        aggregation      = "Total"
        operator         = "GreaterThan"
        threshold        = 21474836481
      }

      window_size = "PT1H"
    }
    {% endfor %}
    {% endfor %}

    {% for proxy in proxies %}
    resource "azurerm_cdn_endpoint" "endpoint_{{ proxy.id }}" {
      name                = "{{ proxy.slug }}"
      profile_name        = azurerm_cdn_profile.profile_{{ proxy.origin.group.id }}_{{ proxy.psg }}.name
      location            = "{{ azure_location }}"
      resource_group_name = data.azurerm_resource_group.this.name

      origin_host_header  = "{{ proxy.origin.domain_name }}"

      origin {
        name      = "upstream"
        host_name = "{{ proxy.origin.domain_name }}"
      }

      global_delivery_rule {
        modify_request_header_action {
          action = "Append"
          name = "Bypass-Rate-Limit-Token"
          value = "{{ bypass_token }}"
        }
      }
    }

    resource "azurerm_monitor_diagnostic_setting" "diagnostic_{{ proxy.id }}" {
      name               = "cdn-diagnostics"
      target_resource_id = azurerm_cdn_endpoint.endpoint_{{ proxy.id }}.id
      storage_account_id = azurerm_storage_account.this.id

      log {
        category = "CoreAnalytics"
        enabled  = true

        retention_policy {
          enabled = true
          days = 90
        }
      }
    }
    {% endfor %}
    """

    def import_state(self, state: Optional[Any]) -> None:
        proxies = Proxy.query.filter(
            Proxy.provider == self.provider,
            Proxy.destroyed.is_(None)
        ).all()
        for proxy in proxies:
            proxy.url = f"https://{proxy.slug}.azureedge.net"
        db.session.commit()
