# Security operations
import os
import sys
import logging
import hashlib
import secrets
import base64

# Setup module path first before any imports
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from Modules.common import setup_module_path, setup_module_logging, get_server_manager_dir, is_admin as common_is_admin, RegistryModule
setup_module_path()

logger: logging.Logger = setup_module_logging("Security")

class SecurityManager(RegistryModule):
    # Auth, password hashing, token gen

    def initialise_from_registry(self):
        # Pull paths from registry
        try:
            self.server_manager_dir = get_server_manager_dir()

            self.paths = {
                "root": self.server_manager_dir,
                "logs": os.path.join(self.server_manager_dir, "logs")
            }

            # Directories are now created in Start-ServerManager.pyw
            logger.info("Security manager ready")
            return True

        except Exception as e:
            logger.error(f"Security init failed: {str(e)}")
            return False

    def generate_token(self, length=32):
        # Random hex token
        return secrets.token_hex(length)

    def hash_password(self, password, salt=None):
        # SHA256 password hash with salt
        if salt is None:
            salt = secrets.token_hex(16)

        password_bytes = password.encode('utf-8')
        salt_bytes = salt.encode('utf-8')

        hash_obj = hashlib.sha256(password_bytes + salt_bytes)
        password_hash = base64.b64encode(hash_obj.digest()).decode('utf-8')

        return {
            "hash": password_hash,
            "salt": salt
        }

    def verify_password(self, password, stored_hash, salt):
        # Check password against stored hash
        password_bytes = password.encode('utf-8')
        salt_bytes = salt.encode('utf-8')

        hash_obj = hashlib.sha256(password_bytes + salt_bytes)
        calculated_hash = base64.b64encode(hash_obj.digest()).decode('utf-8')

        return calculated_hash == stored_hash

    def encrypt_data(self, data, key=None):
        # Encrypt data with an optional key
        try:
            from cryptography.fernet import Fernet

            if key is None:
                key = Fernet.generate_key()
            elif isinstance(key, str):
                # Ensure the key is proper Fernet key format
                try:
                    Fernet(key.encode('utf-8'))
                except (ValueError, Exception):
                    key = Fernet.generate_key()

            if isinstance(data, str):
                data = data.encode('utf-8')

            f = Fernet(key)
            encrypted_data = f.encrypt(data)

            return {
                "data": encrypted_data,
                "key": key
            }
        except ImportError:
            logger.error("Cryptography module not installed. Using base64 encoding instead.")
            # Fallback to simple encoding if cryptography not available
            if isinstance(data, str):
                data = data.encode('utf-8')
            return {
                "data": base64.b64encode(data),
                "key": None
            }
        except Exception as e:
            logger.error(f"Encryption error: {str(e)}")
            return None

    def decrypt_data(self, encrypted_data, key):
        # Decrypt data with the provided key
        try:
            from cryptography.fernet import Fernet

            if isinstance(key, str):
                key = key.encode('utf-8')

            f = Fernet(key)
            decrypted_data = f.decrypt(encrypted_data)

            return decrypted_data
        except ImportError:
            logger.error("Cryptography module not installed. Using base64 decoding instead.")
            # Fallback to simple decoding if cryptography not available
            return base64.b64decode(encrypted_data)
        except Exception as e:
            logger.error(f"Decryption error: {str(e)}")
            return None

# Create instance for easy access
security_manager = SecurityManager()

# Export functions for easy module access
def is_admin():
    # Check if current process has admin privileges
    return common_is_admin()

def generate_token(length=32):
    # Generate a secure random token
    return security_manager.generate_token(length)

def hash_password(password, salt=None):
    # Hash a password with optional salt
    return security_manager.hash_password(password, salt)

def verify_password(password, stored_hash, salt):
    # Verify a password against stored hash and salt
    return security_manager.verify_password(password, stored_hash, salt)

def encrypt_data(data, key=None):
    # Encrypt data with optional key
    return security_manager.encrypt_data(data, key)

def decrypt_data(encrypted_data, key):
    # Decrypt data with the provided key
    return security_manager.decrypt_data(encrypted_data, key)