from pathlib import Path

import yaml

from nebula_cert_manager.models import Registry
from nebula_cert_manager.sops import Sops


REGISTRY_FILENAME = "registry.sops.yaml"
CA_CERT_FILENAME = "ca.crt"
SOPS_CONFIG_FILENAME = ".sops.yaml"


class RegistryManager:
    def __init__(self, registry_dir: Path, sops: Sops):
        self.registry_dir = registry_dir
        self.sops = sops
        self.registry_path = registry_dir / REGISTRY_FILENAME
        self.ca_cert_path = registry_dir / CA_CERT_FILENAME
        self.sops_config_path = registry_dir / SOPS_CONFIG_FILENAME

    def exists(self) -> bool:
        return self.registry_path.exists()

    def _get_sops_config(self) -> Path | None:
        if self.sops_config_path.exists():
            return self.sops_config_path
        return None

    def load(self) -> Registry:
        plaintext = self.sops.decrypt(
            self.registry_path, config_path=self._get_sops_config()
        )
        data = yaml.safe_load(plaintext)
        return Registry.model_validate(data)

    def save(self, registry: Registry) -> None:
        self.registry_dir.mkdir(parents=True, exist_ok=True)
        self._ensure_sops_config()
        data = registry.model_dump(mode="json")
        plaintext = yaml.dump(data, default_flow_style=False, sort_keys=False)
        self.sops.encrypt_to_file(
            self.registry_path, plaintext, config_path=self._get_sops_config()
        )
        self.ca_cert_path.write_text(registry.ca.cert)

    def _ensure_sops_config(self) -> None:
        if self.sops_config_path.exists() or not self.sops.age_key:
            return
        config = {
            "creation_rules": [
                {
                    "path_regex": r".*\.sops\.yaml$",
                    "encrypted_regex": "key$",
                    "age": self.sops.age_key,
                }
            ]
        }
        self.sops_config_path.write_text(
            yaml.dump(config, default_flow_style=False, sort_keys=False)
        )
