#!/usr/bin/env python3
# Copyright 2021 UBITECH Ltd.
# See LICENSE file for licensing details.
#
# Learn more at: https://juju.is/docs/sdk

"""Charm the service.

Refer to the following post for a quick-start guide that will help you
develop a new k8s charm using the Operator Framework:

    https://discourse.charmhub.io/t/4208
"""
import json
import logging

from ops.charm import CharmBase
from ops.main import main
from ops.model import ActiveStatus, BlockedStatus
from opslib.osm.interfaces.mysql import MysqlClient
import requests

logger = logging.getLogger(__name__)


class PowerDNSCharm(CharmBase):
    """Charm the service."""

    log: logging.Logger = None

    def __init__(self, *args):
        super().__init__(*args)
        self.log = logging.getLogger("powerdns")

        self.powerdns_api_key = "changeme"
        self.headers = {"X-API-Key": self.powerdns_api_key}
        self.url = "http://localhost:8081/api/v1/servers/localhost/zones"

        self.mysql_client = MysqlClient(self, "db")
        self.framework.observe(self.on["db"].relation_changed, self.configure_pod)
        self.framework.observe(self.on["db"].relation_broken, self.configure_pod)

        self.framework.observe(self.on["add_zone"].action, self._on_add_zone_action)
        self.framework.observe(
            self.on["delete_zone"].action, self._on_delete_zone_action
        )
        self.framework.observe(self.on["add_domain"].action, self._on_add_domain_action)
        self.framework.observe(
            self.on["delete_domain"].action, self._on_delete_domain_action
        )

        self.framework.observe(self.on.config_changed, self.configure_pod)
        self.framework.observe(self.on.leader_elected, self.configure_pod)

    def _on_add_zone_action(self, event):
        zone = event.params["zone-name"]

        self.log.info("Running add-zone action...")

        payload = {
            "name": zone,
            "kind": "Native",
            "masters": [],
            "nameservers": ["ns1.example.org."],
        }

        r = requests.post(self.url, data=json.dumps(payload), headers=self.headers)
        if r.status_code != 201:
            self.log.info(r.status_code, r.text)
        else:
            self.log.info("Added zone {zone}")

    def _on_delete_zone_action(self, event):
        zone = event.params["zone-name"]

        self.log.info("Running delete-zone action...")

        r = requests.delete(self.url + "/" + zone, headers=self.headers)
        if r.status_code != 204:
            self.log.info(r.status_code, r.text)
        else:
            self.log.info(f"Deleted zone {zone}")

    def _on_add_domain_action(self, event):
        zone = event.params["zone-name"]
        domain = event.params["subdomain"]
        ip = event.params["ip"]

        self.log.info("Running add-domain action...")

        payload = {
            "rrsets": [
                {
                    "name": domain + zone,
                    "type": "A",
                    "ttl": 86400,
                    "changetype": "REPLACE",
                    "records": [{"content": ip}],
                }
            ]
        }

        r = requests.patch(
            self.url + "/" + zone, data=json.dumps(payload), headers=self.headers
        )
        if r.status_code != 204:
            self.log.info(r.status_code, r.text)
        else:
            self.log.info(f"Added record of {domain}{zone} in {ip}")

    def _on_delete_domain_action(self, event):
        zone = event.params["zone-name"]
        domain = event.params["subdomain"]

        self.log.info("Running delete-domain action...")

        payload = {
            "rrsets": [{"name": domain + zone, "type": "A", "changetype": "DELETE"}]
        }

        r = requests.patch(
            self.url + "/" + zone, data=json.dumps(payload), headers=self.headers
        )
        if r.status_code != 204:
            self.log.info(r.status_code, r.text)
        else:
            self.log.info(f"Deleted record of {domain} in zone {zone}")

    def configure_pod(self, _):
        if self.mysql_client.is_missing_data_in_unit():
            self.unit.status = BlockedStatus("missing mysql relation")
            return

        mysql_host = self.mysql_client.host
        mysql_port = self.mysql_client.port
        mysql_root_password = self.mysql_client.root_password
        mysql_root_username = "root"
        mysql_database = self.mysql_client.database

        self.model.pod.set_spec(
            {
                "version": 3,
                "containers": [
                    {
                        "name": "powerdns",
                        "image": "vapostolopoulos/powerdns:latest",
                        "ports": [
                            {
                                "name": "powerdns-tcp",
                                "containerPort": 53,
                                "protocol": "TCP",
                            },
                            {
                                "name": "powerdns-api",
                                "containerPort": 8081,
                                "protocol": "TCP",
                            },
                        ],
                        "kubernetes": {
                            "readinessProbe": {
                                "httpGet": {
                                    "path": "/api/v1/servers",
                                    "port": "powerdns-api",
                                    "httpHeaders": [
                                        {
                                            "name": "X-API-Key",
                                            "value": self.powerdns_api_key,
                                        }
                                    ],
                                }
                            }
                        },
                        "envConfig": {
                            "MYSQL_HOST": mysql_host,
                            "MYSQL_PORT": mysql_port,
                            "MYSQL_USER": mysql_root_username,
                            "MYSQL_PASS": mysql_root_password,
                            "MYSQL_DB": mysql_database,
                        },
                        "args": [
                            "--cache-ttl=120",
                            "--allow-axfr-ips=127.0.0.1,123.1.2.3",
                            "--webserver-address=0.0.0.0",
                            "--webserver-allow-from=0.0.0.0/0,::/0",
                            "--api=yes",
                            "--api-key=" + self.powerdns_api_key,
                        ],
                    }
                ],
            }
        )
        self.unit.status = ActiveStatus()


if __name__ == "__main__":
    main(PowerDNSCharm)
