from abc import ABC
from pathlib import Path
from pydantic import BaseModel
from dotenv import dotenv_values

import typing as T
import logging


class Secret(BaseModel):
    key: str
    value: str


class SecretsManagerPort(ABC):
    def write_secret(self, secret: Secret):
        """Upload a secret to secret vault/manager"""
        raise NotImplementedError
    
    def read_secret(self, key: str) -> Secret:
        """Download a secret from a secrets vault/manager"""
        raise NotImplementedError
    
    def delete_secret(self, key: str):
        """Delete a secret from secret vault/manager"""
        raise NotImplementedError
    
    def list_all_secrets(self) -> T.List[str]:
        """List all secret names/keys from a secrets vault/manager"""
        raise NotImplementedError
    
    def read_all_secrets(self) -> T.List[Secret]:
        """Download all secrets""" 
        raise NotImplementedError
    
    def download_all_to_env_file(self, env_path: Path):
        """Download all secrets from a secrets vault/manager to a `.env` file"""
        
        secrets = self.read_all_secrets()
        with open(env_path, "w") as f: 
            for secret in secrets: 
                f.write(f"{secret.key}={secret.value}\n")

        logging.info(f"✅ Downloaded {len(secrets)} secrets to {str(env_path)}!")


    def upload_from_env_file(self, env_path: Path):
        """Upload all secrets to secret vault/manager from env file"""

        kv_pairs = dotenv_values(env_path)
        for key, value in kv_pairs.items():
            self.write_secret(Secret(key=key, value=value)) 

        logging.info(f"✅ Uploaded secrets from {str(env_path)}!")
    