using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

/// <summary>
/// Gestionnaire de l'authentification via iframe.
/// Orchestre la communication postMessage entre Unity et le site parent.
/// </summary>
public class IframeAuthManager : MonoBehaviour
{
    #region Singleton
    private static IframeAuthManager _instance;
    public static IframeAuthManager Instance
    {
        get
        {
            if (_instance == null)
            {
                GameObject go = new GameObject("IframeAuthManager");
                _instance = go.AddComponent<IframeAuthManager>();
                DontDestroyOnLoad(go);
            }
            return _instance;
        }
    }
    #endregion

    #region Propriétés

    /// <summary>
    /// Indique si l'authentification via iframe est active.
    /// </summary>
    public bool IsIframeAuthActive => PostMessageBridge.Instance.IsInIframe;

    /// <summary>
    /// Indique si l'utilisateur a été authentifié via le token iframe.
    /// </summary>
    public bool IsAuthenticatedViaIframe { get; private set; }

    #endregion

    #region Cycle de vie Unity

    void Awake()
    {
        Debug.Log("═══════════════════════════════════════════════════════");
        Debug.Log("[IframeAuth] Awake() appelé");
        
        if (_instance != null && _instance != this)
        {
            Debug.Log("[IframeAuth] Instance déjà existante, destruction de ce GameObject");
            Destroy(gameObject);
            return;
        }

        _instance = this;
        DontDestroyOnLoad(gameObject);
        Debug.Log("[IframeAuth] Instance créée et marquée DontDestroyOnLoad");

        // S'abonner à l'événement de réception de token
        Debug.Log("[IframeAuth] Abonnement à PostMessageBridge.OnTokenReceived");
        PostMessageBridge.Instance.OnTokenReceived += OnTokenReceivedFromParent;
        Debug.Log("[IframeAuth] ✓ Abonnement effectué");
        Debug.Log("═══════════════════════════════════════════════════════");
    }

    void Start()
    {
        Debug.Log("═══════════════════════════════════════════════════════");
        Debug.Log("[IframeAuth] Start() appelé");
        
        // NOTE IMPORTANTE : 
        // L'origin autorisé est configuré par défaut à "https://www.newsassurancespro.com"
        // dans le fichier .jslib. Pour les tests, vous pouvez le changer manuellement
        // en appelant PostMessageBridge.Instance.SetParentOrigin("https://votre-domaine-test.com")
        // depuis un autre script ou via la console Unity.
        
        // Vérifier au démarrage s'il y a un token du parent
        CheckForParentToken();
        Debug.Log("═══════════════════════════════════════════════════════");
    }

    void OnDestroy()
    {
        if (_instance == this)
        {
            // Se désabonner de l'événement (vérifier que l'instance existe et que l'app ne se ferme pas)
            var bridge = PostMessageBridge.Instance;
            if (bridge != null)
            {
                bridge.OnTokenReceived -= OnTokenReceivedFromParent;
            }
            _instance = null;
        }
    }

    #endregion

    #region Méthodes publiques

    /// <summary>
    /// Vérifie s'il y a un token reçu du parent et tente une authentification.
    /// </summary>
    public void CheckForParentToken()
    {
        Debug.Log("[IframeAuth] ─────────────────────────────────────────");
        Debug.Log("[IframeAuth] CheckForParentToken() appelé");
        Debug.Log($"[IframeAuth] PostMessageBridge.Instance.IsInIframe: {PostMessageBridge.Instance.IsInIframe}");
        
        if (!PostMessageBridge.Instance.IsInIframe)
        {
            Debug.Log("[IframeAuth] ⚠ Pas dans une iframe - authentification standard");
            return;
        }

        Debug.Log("[IframeAuth] ✓ Dans une iframe - vérification du token parent...");

        // Vérifier si un token existe déjà dans UserDataManager (session précédente)
        Debug.Log("[IframeAuth] Vérification de UserDataManager...");
        if (UserDataManager.Instance != null)
        {
            Debug.Log($"[IframeAuth] UserDataManager.Instance existe");
            bool isLoggedIn = UserDataManager.Instance.IsLoggedIn();
            Debug.Log($"[IframeAuth] UserDataManager.Instance.IsLoggedIn(): {isLoggedIn}");
            
            if (isLoggedIn)
            {
                Debug.Log("[IframeAuth] ✓ Utilisateur déjà authentifié (session existante)");
                IsAuthenticatedViaIframe = false; // Pas via iframe, session locale
                return;
            }
        }
        else
        {
            Debug.LogWarning("[IframeAuth] UserDataManager.Instance est null !");
        }

        // Vérifier si un token a été reçu du parent
        Debug.Log("[IframeAuth] Vérification du token parent...");
        bool hasToken = PostMessageBridge.Instance.HasToken;
        Debug.Log($"[IframeAuth] PostMessageBridge.Instance.HasToken: {hasToken}");
        
        if (hasToken)
        {
            Debug.Log("[IframeAuth] ✓ Token détecté, récupération...");
            string token = PostMessageBridge.Instance.GetToken();
            Debug.Log($"[IframeAuth] Token récupéré: {(string.IsNullOrEmpty(token) ? "VIDE OU NULL" : $"{token.Length} caractères")}");
            
            if (!string.IsNullOrEmpty(token))
            {
                Debug.Log("[IframeAuth] 🔐 Démarrage de l'authentification avec le token parent...");
                StartCoroutine(AuthenticateWithToken(token));
            }
            else
            {
                Debug.LogWarning("[IframeAuth] ⚠ Token vide ou null malgré HasToken = true");
            }
        }
        else
        {
            Debug.Log("[IframeAuth] ⚠ Aucun token reçu du parent - attente ou login standard");
        }
        Debug.Log("[IframeAuth] ─────────────────────────────────────────");
    }

    /// <summary>
    /// Notifie le parent qu'une connexion a été effectuée avec succès.
    /// À appeler après une connexion réussie via le formulaire de login.
    /// </summary>
    public void NotifyParentOfLogin()
    {
        if (!PostMessageBridge.Instance.IsInIframe)
        {
            Debug.Log("[IframeAuth] Pas dans une iframe - notification ignorée");
            return;
        }

        if (UserDataManager.Instance == null || !UserDataManager.Instance.IsLoggedIn())
        {
            Debug.LogWarning("[IframeAuth] Impossible de notifier : utilisateur non connecté");
            return;
        }

        string token = UserDataManager.Instance.token;
        if (string.IsNullOrEmpty(token))
        {
            Debug.LogWarning("[IframeAuth] Impossible de notifier : token vide");
            return;
        }

        Debug.Log("[IframeAuth] Notification du parent suite à la connexion...");
        bool success = PostMessageBridge.Instance.NotifyLogin(token);

        if (success)
        {
            Debug.Log("[IframeAuth] ✓ Parent notifié avec succès");
        }
        else
        {
            Debug.LogError("[IframeAuth] ⛔ Échec de la notification du parent");
        }
    }

    #endregion

    #region Méthodes privées

    /// <summary>
    /// Callback appelé quand un token est reçu du parent.
    /// </summary>
    private void OnTokenReceivedFromParent(string token)
    {
        Debug.Log("═══════════════════════════════════════════════════════");
        Debug.Log("[IframeAuth] 📨 OnTokenReceivedFromParent() CALLBACK DÉCLENCHÉ !");
        Debug.Log($"[IframeAuth] Token reçu du parent (callback) - longueur: {token?.Length ?? 0}");
        
        if (string.IsNullOrEmpty(token))
        {
            Debug.LogWarning("[IframeAuth] ⚠ Token vide ou null dans le callback");
            return;
        }

        // Si l'utilisateur est déjà connecté, ignorer le nouveau token
        if (UserDataManager.Instance != null && UserDataManager.Instance.IsLoggedIn())
        {
            Debug.Log("[IframeAuth] Utilisateur déjà connecté - token parent ignoré");
            return;
        }

        // Tenter l'authentification avec ce token
        Debug.Log("[IframeAuth] 🔐 Démarrage de l'authentification avec le token reçu...");
        StartCoroutine(AuthenticateWithToken(token));
        Debug.Log("═══════════════════════════════════════════════════════");
    }

    /// <summary>
    /// Authentifie l'utilisateur avec un token JWT reçu du parent.
    /// </summary>
    private IEnumerator AuthenticateWithToken(string token)
    {
        Debug.Log("═══════════════════════════════════════════════════════");
        Debug.Log("[IframeAuth] 🔐 AuthenticateWithToken() DÉMARRÉ");
        Debug.Log($"[IframeAuth] Token (longueur): {token?.Length ?? 0}");
        Debug.Log($"[IframeAuth] Token (début): {(string.IsNullOrEmpty(token) ? "VIDE" : token.Substring(0, System.Math.Min(50, token.Length)))}...");

        // Récupérer l'URL de vérification du token depuis la configuration
        Debug.Log("[IframeAuth] Récupération de l'URL de vérification...");
        string verifyUrl = GeneralConfigManager.Instance?.GetAuthVerifyTokenUrl() ?? "";
        Debug.Log($"[IframeAuth] URL de vérification: {(string.IsNullOrEmpty(verifyUrl) ? "NON DÉFINIE" : verifyUrl)}");
        
        if (string.IsNullOrEmpty(verifyUrl))
        {
            Debug.LogError("[IframeAuth] ⛔ URL de vérification du token non définie dans general-config.json");
            Debug.LogError("[IframeAuth] Ajoutez 'authVerifyToken' dans la section 'apiUrls' de general-config.json");
            Debug.Log("═══════════════════════════════════════════════════════");
            yield break;
        }
        
        Debug.Log("[IframeAuth] ✓ URL de vérification OK, préparation de la requête...");

        // Préparer la requête avec le token en en-tête Authorization
        Debug.Log($"[IframeAuth] Création de la requête GET vers: {verifyUrl}");
        using (UnityWebRequest www = UnityWebRequest.Get(verifyUrl))
        {
            Debug.Log($"[IframeAuth] Ajout du header Authorization: Bearer {token.Substring(0, System.Math.Min(20, token.Length))}...");
            www.SetRequestHeader("Authorization", $"Bearer {token}");
            www.SetRequestHeader("Content-Type", "application/json");

            Debug.Log("[IframeAuth] Envoi de la requête...");
            yield return www.SendWebRequest();

            Debug.Log($"[IframeAuth] Requête terminée - Result: {www.result}");
            Debug.Log($"[IframeAuth] Code HTTP: {www.responseCode}");

            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[IframeAuth] ⛔ Échec de la vérification du token: {www.error}");
                Debug.LogError($"[IframeAuth] Code HTTP: {www.responseCode}");
                Debug.LogError($"[IframeAuth] Réponse: {www.downloadHandler?.text ?? "VIDE"}");
                
                // En cas d'erreur, effacer le token
                Debug.Log("[IframeAuth] Nettoyage du token...");
                PostMessageBridge.Instance.ClearToken();
                Debug.Log("═══════════════════════════════════════════════════════");
                yield break;
            }

            // Parser la réponse
            string jsonResponse = www.downloadHandler.text;
            Debug.Log($"[IframeAuth] ✓ Réponse du serveur reçue ({jsonResponse.Length} caractères)");
            Debug.Log($"[IframeAuth] Réponse JSON: {jsonResponse}");

            try
            {
                Debug.Log("[IframeAuth] Parsing de la réponse JSON...");
                TokenVerifyResponse response = JsonUtility.FromJson<TokenVerifyResponse>(jsonResponse);

                Debug.Log($"[IframeAuth] Response parsée - status: {response?.status ?? "NULL"}");
                Debug.Log($"[IframeAuth] Response.data: {(response?.data != null ? "PRÉSENT" : "NULL")}");

                if (response != null && response.status == "success" && response.data != null)
                {
                    Debug.Log("[IframeAuth] ✓✓✓ Token valide - authentification réussie ✓✓✓");
                    Debug.Log($"[IframeAuth] User ID: {response.data.user_id}");
                    Debug.Log($"[IframeAuth] Email: {response.data.email}");

                    // Stocker les données utilisateur
                    if (UserDataManager.Instance != null)
                    {
                        Debug.Log("[IframeAuth] Conversion des données pour UserDataManager...");
                        // Convertir TokenVerifyResponseData en LoginResponseData
                        LoginResponseData loginData = new LoginResponseData
                        {
                            token = token,
                            user_id = response.data.user_id,
                            email = response.data.email,
                            is_napro_membership = response.data.is_napro_membership,
                            is_cl_membership = response.data.is_cl_membership,
                            is_annie_membership = response.data.is_annie_membership,
                            is_ujsa_membership = response.data.is_ujsa_membership,
                            email_validated = response.data.email_validated,
                            profil_completed = response.data.profil_completed,
                            about_me = response.data.about_me,
                            company = response.data.company
                        };

                        Debug.Log("[IframeAuth] Stockage des données utilisateur...");
                        UserDataManager.Instance.StoreUserData(loginData);
                        IsAuthenticatedViaIframe = true;

                        Debug.Log("[IframeAuth] ✓✓✓ Données utilisateur stockées avec succès ✓✓✓");
                        Debug.Log($"[IframeAuth] IsAuthenticatedViaIframe: {IsAuthenticatedViaIframe}");
                        
                        // Notifier que l'utilisateur est maintenant connecté
                        // (le système de login popup doit vérifier IsLoggedIn() pour se masquer automatiquement)
                        
                        // Recharger la configuration du projet depuis l'API avec le token utilisateur
                        MainSceneManager mainSceneManager = FindFirstObjectByType<MainSceneManager>();
                        if (mainSceneManager != null)
                        {
                            Debug.Log("[IframeAuth] 🔄 Déclenchement du rafraîchissement de la configuration du projet...");
                            mainSceneManager.RefreshProjectConfiguration();
                        }
                        else
                        {
                            Debug.Log("[IframeAuth] ⚠️ MainSceneManager non trouvé - rafraîchissement ignoré (scène Main pas active)");
                        }
                    }
                    else
                    {
                        Debug.LogError("[IframeAuth] ⛔ UserDataManager.Instance est NULL !");
                    }
                }
                else
                {
                    Debug.LogError("[IframeAuth] ⛔ Token invalide ou réponse incorrecte");
                    Debug.LogError($"[IframeAuth] Status: {response?.status}");
                    Debug.LogError($"[IframeAuth] Message: {response?.message}");
                    PostMessageBridge.Instance.ClearToken();
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[IframeAuth] ⛔ Erreur lors du parsing de la réponse: {e.Message}");
                Debug.LogError($"[IframeAuth] Stack trace: {e.StackTrace}");
                Debug.LogError($"[IframeAuth] Réponse reçue: {jsonResponse}");
                PostMessageBridge.Instance.ClearToken();
            }
        }
        
        Debug.Log("═══════════════════════════════════════════════════════");
    }

    #endregion
}

#region Classes de données pour la vérification du token

/// <summary>
/// Réponse de l'API de vérification du token.
/// </summary>
[System.Serializable]
public class TokenVerifyResponse
{
    public string status;
    public TokenVerifyResponseData data;
    public string message;
}

/// <summary>
/// Données utilisateur retournées par l'API de vérification du token.
/// </summary>
[System.Serializable]
public class TokenVerifyResponseData
{
    public int user_id;
    public string email;
    public bool is_napro_membership;
    public bool is_cl_membership;
    public bool is_annie_membership;
    public bool is_ujsa_membership;
    public bool email_validated;
    public bool profil_completed;
    public string about_me;
    public CompanyInfo company;
}

#endregion

