package com.example.boidelov3.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import java.security.MessageDigest;
import java.security.SecureRandom;

/**
 * Classe utilitaire pour la gestion sécurisée des clés API et configuration sensible.
 *
 * SECURITY PRINCIPLES:
 * - Les clés API ne sont JAMAIS stockées en dur dans le code
 * - Utilise SharedPreferences chiffrés (doit être combiné avec AndroidX Security pour un chiffrage réel)
 * - Valide les clés API avant utilisation
 * - Fournit des méthodes pour nettoyer les données sensibles
 *
 * RECOMMANDATION: Pour une production sécurisée, utilisez AndroidX Security Library:
 * implementation "androidx.security:security-crypto:1.1.0-alpha06"
 * Et remplace les SharedPreferences par EncryptedSharedPreferences
 */
public class SecureConfig {

    private static final String TAG = "SecureConfig";
    private static final String PREFS_NAME = "SecureConfig";
    private static final String KEY_API_KEY = "api_key_openai";
    private static final String KEY_API_KEY_OPENROUTER = "api_key_openrouter";
    private static final String KEY_API_KEY_ZAI = "api_key_zai";

    private final SharedPreferences sharedPreferences;
    private final SecureRandom secureRandom;

    /**
     * Constructeur
     * @param context Contexte de l'application
     */
    public SecureConfig(Context context) {
        // Pour plus de sécurité, utiliser EncryptedSharedPreferences d'AndroidX Security
        // Pour l'instant, on utilise des SharedPreferences standards avec des avertissements
        this.sharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
        this.secureRandom = new SecureRandom();
    }

    /**
     * Sauvegarde une clé API de manière sécurisée
     * NOTE: Pour une vraie sécurité, utilisez EncryptedSharedPreferences d'AndroidX Security
     *
     * @param provider Le fournisseur (openai, openrouter, zai)
     * @param apiKey La clé API à stocker
     * @return true si sauvegardé avec succès
     */
    public boolean saveApiKey(String provider, String apiKey) {
        if (apiKey == null || apiKey.trim().isEmpty()) {
            Log.w(TAG, "Tentative de sauvegarder une clé API vide");
            return false;
        }

        // Valider la clé avant sauvegarde
        if (!validateApiKeyFormat(provider, apiKey)) {
            Log.w(TAG, "Format de clé API invalide pour " + provider);
            return false;
        }

        SharedPreferences.Editor editor = sharedPreferences.edit();
        String key = getPrefKeyForProvider(provider);
        editor.putString(key, apiKey);
        boolean success = editor.commit();

        if (success) {
            Log.i(TAG, "Clé API sauvegardée pour " + provider);
        } else {
            Log.e(TAG, "Erreur lors de la sauvegarde de la clé API");
        }

        return success;
    }

    /**
     * Récupère une clé API stockée
     *
     * @param provider Le fournisseur (openai, openrouter, zai)
     * @return La clé API ou null si non trouvée
     */
    public String getApiKey(String provider) {
        if (provider == null || provider.trim().isEmpty()) {
            return null;
        }
        String key = getPrefKeyForProvider(provider);
        return sharedPreferences.getString(key, null);
    }

    /**
     * Supprime une clé API stockée
     *
     * @param provider Le fournisseur
     * @return true si supprimée avec succès
     */
    public boolean removeApiKey(String provider) {
        if (provider == null || provider.trim().isEmpty()) {
            Log.w(TAG, "Provider null ou vide pour removeApiKey");
            return false;
        }

        SharedPreferences.Editor editor = sharedPreferences.edit();
        String key = getPrefKeyForProvider(provider);
        editor.remove(key);
        boolean success = editor.commit();

        if (success) {
            Log.i(TAG, "Clé API supprimée pour " + provider);
        }

        return success;
    }

    /**
     * Supprime toutes les clés API stockées
     * Utiliser cette méthode lors de la déconnexion ou pour nettoyer les données
     */
    public void clearAllApiKeys() {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.remove(KEY_API_KEY);
        editor.remove(KEY_API_KEY_OPENROUTER);
        editor.remove(KEY_API_KEY_ZAI);
        editor.apply();
        Log.i(TAG, "Toutes les clés API ont été supprimées");
    }

    /**
     * Vérifie si une clé API existe pour un provider
     *
     * @param provider Le fournisseur
     * @return true si une clé existe
     */
    public boolean hasApiKey(String provider) {
        if (provider == null || provider.trim().isEmpty()) {
            return false;
        }
        String key = getPrefKeyForProvider(provider);
        return sharedPreferences.contains(key) && sharedPreferences.getString(key, null) != null;
    }

    /**
     * Valide le format d'une clé API selon le provider
     *
     * @param provider Le fournisseur (openai, openrouter, zai)
     * @param apiKey La clé API à valider
     * @return true si le format est valide
     */
    public boolean validateApiKeyFormat(String provider, String apiKey) {
        if (apiKey == null || apiKey.trim().isEmpty()) {
            return false;
        }

        if (provider == null || provider.trim().isEmpty()) {
            Log.w(TAG, "Provider null ou vide");
            return false;
        }

        String trimmedKey = apiKey.trim();

        switch (provider.toLowerCase().trim()) {
            case "openai":
                // Les clés OpenAI commencent par "sk-"
                return trimmedKey.startsWith("sk-") && trimmedKey.length() >= 20;

            case "openrouter":
                // Les clés OpenRouter commencent par "sk-or-"
                return trimmedKey.startsWith("sk-or-") && trimmedKey.length() >= 20;

            case "zai":
                // Les clés Z.ai/Anthropic commencent par "sk-ant-"
                return trimmedKey.startsWith("sk-ant-") && trimmedKey.length() >= 20;

            default:
                Log.w(TAG, "Provider inconnu: " + provider);
                return false;
        }
    }

    /**
     * Génère un hash sécurisé d'une clé pour vérification (stockage local)
     * Ne stocke JAMAIS la clé en clair dans les logs
     *
     * @param apiKey La clé API
     * @return Le hash de la clé
     */
    public String hashApiKey(String apiKey) {
        if (apiKey == null) {
            Log.w(TAG, "Tentative de hasher une clé API null");
            return null;
        }
        
        if (apiKey.trim().isEmpty()) {
            Log.w(TAG, "Tentative de hasher une clé API vide");
            return null;
        }
        
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(apiKey.getBytes("UTF-8"));
            return android.util.Base64.encodeToString(hash, android.util.Base64.NO_WRAP);
        } catch (java.security.NoSuchAlgorithmException e) {
            Log.e(TAG, "SHA-256 non disponible sur cet appareil - hash impossible", e);
            return null;
        } catch (java.io.UnsupportedEncodingException e) {
            Log.e(TAG, "UTF-8 encoding non supporté - impossible", e);
            return null;
        }
    }

    /**
     * Génère une chaîne aléatoire sécurisée pour utilisation comme nonce ou token
     *
     * @param length Longueur de la chaîne
     * @return Chaîne aléatoire sécurisée
     */
    public String generateSecureToken(int length) {
        byte[] token = new byte[length];
        secureRandom.nextBytes(token);
        return android.util.Base64.encodeToString(token, android.util.Base64.NO_WRAP);
    }

    /**
     * Retourne la clé SharedPreferences appropriée selon le provider
     */
    private String getPrefKeyForProvider(String provider) {
        if (provider == null) {
            return KEY_API_KEY; // Default to OpenAI key
        }
        switch (provider.toLowerCase().trim()) {
            case "openrouter":
                return KEY_API_KEY_OPENROUTER;
            case "zai":
                return KEY_API_KEY_ZAI;
            case "openai":
            default:
                return KEY_API_KEY;
        }
    }

    /**
     * Vérifie si des clés API sont stockées (pour vérifier la configuration)
     *
     * @return true si au moins une clé API est configurée
     */
    public boolean isAnyApiKeyConfigured() {
        return hasApiKey("openai") || hasApiKey("openrouter") || hasApiKey("zai");
    }
}
