"""
Nexus Enigma HTTP Client

End-to-end encryption for Nexus data ingestion via HTTP.
Uses AES-256-GCM with daily key rotation via HKDF.
"""

import base64
import json
import os
from datetime import datetime, timezone
from typing import Any, Dict

import requests
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.kdf.hkdf import HKDF


class NexusEnigma:
    """
    Nexus Enigma client for sending encrypted data via HTTP.
    
    Example:
        client = NexusEnigma(
            app_key="my_app_key",
            master_secret="base64_encoded_secret_from_nexus",
            base_url="http://localhost:8080"
        )
        
        result = client.send({"temperature": 25.5, "humidity": 60})
        print(result)
    """
    
    NONCE_LENGTH = 12  # 96 bits for GCM
    KEY_LENGTH = 32    # 256 bits for AES-256
    
    def __init__(
        self, 
        app_key: str, 
        master_secret: str, 
        base_url: str = "http://localhost:8080",
        secret_version: int = 1
    ):
        """
        Initialize the Nexus Enigma client.
        
        Args:
            app_key: Your application's app_key from Nexus
            master_secret: Base64-encoded master secret from Nexus UI
            base_url: Nexus API base URL
            secret_version: Secret version for key rotation (default: 1)
        """
        self.app_key = app_key
        self.master_secret = base64.b64decode(master_secret)
        self.base_url = base_url.rstrip('/')
        self.secret_version = secret_version
    
    def send(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Send encrypted data to Nexus.
        
        Args:
            data: Dictionary payload to encrypt and send
            
        Returns:
            Response from Nexus API as dictionary
        """
        today = self._get_today_date()
        key = self._derive_key_for_date(today)
        ciphertext, nonce = self._encrypt(json.dumps(data), key)
        
        payload = {
            "encrypted": True,
            "keyDate": today,
            "secretVersion": self.secret_version,
            "nonce": base64.b64encode(nonce).decode('utf-8'),
            "data": base64.b64encode(ciphertext).decode('utf-8')
        }
        
        response = requests.post(
            f"{self.base_url}/ingress",
            headers={
                "Content-Type": "application/json",
                "X-API-Key": self.app_key
            },
            json=payload
        )
        
        return response.json()
    
    def _get_today_date(self) -> str:
        """Get today's date in YYYY-MM-DD format (UTC)."""
        return datetime.now(timezone.utc).strftime("%Y-%m-%d")
    
    def _derive_key_for_date(self, date: str) -> bytes:
        """
        Derive daily encryption key using HKDF.
        
        Args:
            date: Date string in YYYY-MM-DD format
            
        Returns:
            32-byte AES key
        """
        # MUST match Go server: salt=None, info="nexus-enigma-{appKey}-{date}"
        info = f"nexus-enigma-{self.app_key}-{date}"
        hkdf = HKDF(
            algorithm=hashes.SHA256(),
            length=self.KEY_LENGTH,
            salt=None,
            info=info.encode('utf-8'),
            backend=default_backend()
        )
        return hkdf.derive(self.master_secret)
    
    def _encrypt(self, plaintext: str, key: bytes) -> tuple:
        """
        Encrypt data using AES-256-GCM.
        
        Args:
            plaintext: String to encrypt
            key: 32-byte AES key
            
        Returns:
            Tuple of (ciphertext, nonce)
        """
        nonce = os.urandom(self.NONCE_LENGTH)
        aesgcm = AESGCM(key)
        ciphertext = aesgcm.encrypt(nonce, plaintext.encode('utf-8'), None)
        return ciphertext, nonce


def create_client(
    app_key: str, 
    master_secret: str, 
    base_url: str = "http://localhost:8080"
) -> NexusEnigma:
    """Create a new Nexus Enigma HTTP client."""
    return NexusEnigma(app_key=app_key, master_secret=master_secret, base_url=base_url)
