#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Git Pusher - Credentials Manager
Gère les credentials de manière sécurisée via Splunk storage/passwords
ou via un fichier chiffré local.
"""

import os
import sys
import json
import base64
import hashlib
from pathlib import Path

# Chemin vers le fichier de credentials chiffré
CREDENTIALS_FILE = "/opt/splunk/etc/apps/pusher_app_prem/local/.credentials"
ENCRYPTION_KEY_FILE = "/opt/splunk/etc/apps/pusher_app_prem/local/.key"


def get_machine_id():
    """Obtenir un identifiant unique de la machine pour le chiffrement"""
    machine_id = ""
    
    # Essayer différentes sources
    try:
        with open('/etc/machine-id', 'r') as f:
            machine_id = f.read().strip()
    except:
        pass
    
    if not machine_id:
        try:
            import socket
            machine_id = socket.gethostname()
        except:
            machine_id = "default_key"
    
    return machine_id


def derive_key(password, salt=None):
    """Dériver une clé de chiffrement à partir d'un mot de passe"""
    if salt is None:
        salt = get_machine_id().encode()
    
    # Utiliser PBKDF2-like avec SHA256
    key = hashlib.pbkdf2_hmac(
        'sha256',
        password.encode(),
        salt,
        100000
    )
    return base64.b64encode(key).decode()


def simple_encrypt(data, key):
    """Chiffrement simple XOR (pour une sécurité basique)"""
    # Pour une vraie sécurité, utiliser cryptography.fernet
    key_bytes = key.encode() * (len(data) // len(key) + 1)
    encrypted = bytes([a ^ b for a, b in zip(data.encode(), key_bytes[:len(data)])])
    return base64.b64encode(encrypted).decode()


def simple_decrypt(encrypted_data, key):
    """Déchiffrement simple XOR"""
    try:
        data = base64.b64decode(encrypted_data)
        key_bytes = key.encode() * (len(data) // len(key) + 1)
        decrypted = bytes([a ^ b for a, b in zip(data, key_bytes[:len(data)])])
        return decrypted.decode()
    except Exception as e:
        return None


def get_encryption_key():
    """Obtenir ou créer la clé de chiffrement"""
    if os.path.exists(ENCRYPTION_KEY_FILE):
        with open(ENCRYPTION_KEY_FILE, 'r') as f:
            return f.read().strip()
    else:
        # Générer une nouvelle clé basée sur la machine
        key = derive_key(get_machine_id())
        
        # Sauvegarder la clé
        os.makedirs(os.path.dirname(ENCRYPTION_KEY_FILE), exist_ok=True)
        with open(ENCRYPTION_KEY_FILE, 'w') as f:
            f.write(key)
        
        # Protéger le fichier
        os.chmod(ENCRYPTION_KEY_FILE, 0o600)
        
        return key


def save_credentials(username, password):
    """Sauvegarder les credentials de manière chiffrée"""
    key = get_encryption_key()
    
    credentials = {
        'username': username,
        'password': simple_encrypt(password, key)
    }
    
    os.makedirs(os.path.dirname(CREDENTIALS_FILE), exist_ok=True)
    
    with open(CREDENTIALS_FILE, 'w') as f:
        json.dump(credentials, f)
    
    # Protéger le fichier
    os.chmod(CREDENTIALS_FILE, 0o600)
    
    print(f"✓ Credentials saved securely to {CREDENTIALS_FILE}")


def load_credentials():
    """Charger les credentials chiffrés"""
    if not os.path.exists(CREDENTIALS_FILE):
        return None, None
    
    try:
        key = get_encryption_key()
        
        with open(CREDENTIALS_FILE, 'r') as f:
            credentials = json.load(f)
        
        username = credentials.get('username')
        encrypted_password = credentials.get('password')
        
        password = simple_decrypt(encrypted_password, key)
        
        return username, password
    
    except Exception as e:
        print(f"Error loading credentials: {e}", file=sys.stderr)
        return None, None


def delete_credentials():
    """Supprimer les credentials stockés"""
    if os.path.exists(CREDENTIALS_FILE):
        os.remove(CREDENTIALS_FILE)
        print("✓ Credentials deleted")
    else:
        print("No credentials file found")


def get_credentials_for_script():
    """
    Fonction utilisée par le script de démarrage pour obtenir les credentials.
    Retourne username et password, ou None si non configurés.
    """
    username, password = load_credentials()
    
    if username and password:
        return username, password
    
    # Fallback sur les variables d'environnement
    env_user = os.environ.get('SPLUNK_USERNAME')
    env_pass = os.environ.get('SPLUNK_PASSWORD')
    
    if env_user and env_pass:
        return env_user, env_pass
    
    return None, None


# ============================================
# CLI
# ============================================

def interactive_setup():
    """Configuration interactive des credentials"""
    print("=" * 50)
    print("Git Pusher - Credentials Setup")
    print("=" * 50)
    print()
    print("This will securely store your Splunk credentials.")
    print(f"Credentials will be encrypted and saved to:")
    print(f"  {CREDENTIALS_FILE}")
    print()
    
    username = input("Splunk Username [admin]: ").strip() or "admin"
    
    import getpass
    password = getpass.getpass("Splunk Password: ")
    
    if not password:
        print("Error: Password cannot be empty")
        return
    
    # Confirmer
    password2 = getpass.getpass("Confirm Password: ")
    
    if password != password2:
        print("Error: Passwords do not match")
        return
    
    save_credentials(username, password)
    print()
    print("✓ Credentials configured successfully!")
    print()
    print("You can now start Git Pusher without specifying credentials:")
    print("  ./start_git_pusher.sh start")


def show_status():
    """Afficher le statut des credentials"""
    print("=" * 50)
    print("Credentials Status")
    print("=" * 50)
    
    if os.path.exists(CREDENTIALS_FILE):
        print(f"✓ Credentials file exists: {CREDENTIALS_FILE}")
        
        username, password = load_credentials()
        if username:
            print(f"  Username: {username}")
            print(f"  Password: {'*' * len(password) if password else 'ERROR'}")
        else:
            print("  Error: Could not decrypt credentials")
    else:
        print("✗ No credentials file found")
        print()
        print("Run: python credentials_manager.py setup")


if __name__ == '__main__':
    if len(sys.argv) < 2:
        show_status()
        sys.exit(0)
    
    command = sys.argv[1]
    
    if command == 'setup':
        interactive_setup()
    
    elif command == 'status':
        show_status()
    
    elif command == 'delete':
        delete_credentials()
    
    elif command == 'get':
        # Pour utilisation dans les scripts bash
        username, password = get_credentials_for_script()
        if username and password:
            print(f"{username}")
            print(f"{password}")
        else:
            sys.exit(1)
    
    elif command == 'export':
        # Exporter pour utilisation dans bash
        username, password = get_credentials_for_script()
        if username and password:
            print(f"export SPLUNK_USERNAME='{username}'")
            print(f"export SPLUNK_PASSWORD='{password}'")
        else:
            print("# No credentials found", file=sys.stderr)
            sys.exit(1)
    
    else:
        print("Usage: python credentials_manager.py [setup|status|delete|get|export]")
        print()
        print("Commands:")
        print("  setup   - Configure credentials interactively")
        print("  status  - Show credentials status")
        print("  delete  - Delete stored credentials")
        print("  get     - Output credentials (for scripts)")
        print("  export  - Output as bash export commands")