"""
Interface de connexion pour Web Sentinel
Fenêtre tkinter moderne pour l'authentification
"""

import tkinter as tk
from tkinter import ttk, messagebox
from typing import Optional, Callable, Tuple
import webbrowser
import threading

from .auth_manager import AuthManager
from ..gui.i18n import localization


class LoginDialog:
    """Fenêtre de connexion moderne pour Web Sentinel."""
    
    def __init__(self, parent: Optional[tk.Widget] = None, auth_manager: Optional[AuthManager] = None):
        self.parent = parent
        self.auth_manager = auth_manager or AuthManager()
        self.result: Optional[bool] = None
        self.window: Optional[tk.Toplevel] = None
        
        # Variables
        self.email_var = tk.StringVar()
        self.password_var = tk.StringVar()
        self.remember_var = tk.BooleanVar()
        self.show_password_var = tk.BooleanVar()
        
        # État
        self.is_loading = False
        
        # Callbacks
        self.on_success: Optional[Callable] = None
        self.on_cancel: Optional[Callable] = None
    
    def show(self, modal: bool = True) -> Optional[bool]:
        """Afficher la fenêtre de connexion."""
        self._create_window()
        
        if modal and self.window:
            # Fenêtre modale
            self.window.transient(self.parent)
            self.window.grab_set()
            self.window.wait_window()
            return self.result
        
        return None
    
    def _create_window(self) -> None:
        """Créer la fenêtre de connexion."""
        if self.parent:
            self.window = tk.Toplevel(self.parent)
        else:
            self.window = tk.Tk()
        
        self.window.title("Web Sentinel - Connexion")
        self.window.geometry("450x600")
        self.window.resizable(False, False)
        
        # Centrer la fenêtre
        self.window.update_idletasks()
        x = (self.window.winfo_screenwidth() // 2) - (450 // 2)
        y = (self.window.winfo_screenheight() // 2) - (600 // 2)
        self.window.geometry(f"450x600+{x}+{y}")
        
        # Style moderne
        style = ttk.Style()
        style.theme_use('clam')
        
        # Container principal
        main_frame = ttk.Frame(self.window, padding="30")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        self._create_header(main_frame)
        self._create_login_form(main_frame)
        self._create_actions(main_frame)
        self._create_footer(main_frame)
        
        # Focus sur email
        self.email_entry.focus_set()
        
        # Gérer fermeture
        self.window.protocol("WM_DELETE_WINDOW", self._on_cancel)
    
    def _create_header(self, parent: ttk.Frame) -> None:
        """Créer l'en-tête."""
        # Logo/Titre
        header_frame = ttk.Frame(parent)
        header_frame.pack(fill=tk.X, pady=(0, 30))
        
        title_label = ttk.Label(
            header_frame,
            text="🛡️ Web Sentinel",
            font=("Arial", 24, "bold"),
            foreground="#2563eb"
        )
        title_label.pack()
        
        subtitle_label = ttk.Label(
            header_frame,
            text="Connectez-vous à votre compte",
            font=("Arial", 11),
            foreground="#6b7280"
        )
        subtitle_label.pack(pady=(5, 0))
    
    def _create_login_form(self, parent: ttk.Frame) -> None:
        """Créer le formulaire de connexion."""
        form_frame = ttk.LabelFrame(parent, text="Connexion", padding="20")
        form_frame.pack(fill=tk.X, pady=(0, 20))
        
        # Email
        email_label = ttk.Label(form_frame, text="Adresse email :")
        email_label.pack(anchor=tk.W, pady=(0, 5))
        
        self.email_entry = ttk.Entry(
            form_frame,
            textvariable=self.email_var,
            font=("Arial", 11),
            width=35
        )
        self.email_entry.pack(fill=tk.X, pady=(0, 15))
        
        # Mot de passe
        password_label = ttk.Label(form_frame, text="Mot de passe :")
        password_label.pack(anchor=tk.W, pady=(0, 5))
        
        password_frame = ttk.Frame(form_frame)
        password_frame.pack(fill=tk.X, pady=(0, 15))
        
        self.password_entry = ttk.Entry(
            password_frame,
            textvariable=self.password_var,
            show="•",
            font=("Arial", 11)
        )
        self.password_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # Bouton afficher/masquer mot de passe
        toggle_btn = ttk.Checkbutton(
            password_frame,
            text="👁️",
            variable=self.show_password_var,
            command=self._toggle_password_visibility
        )
        toggle_btn.pack(side=tk.RIGHT, padx=(5, 0))
        
        # Se souvenir de moi
        remember_check = ttk.Checkbutton(
            form_frame,
            text="Se souvenir de moi",
            variable=self.remember_var
        )
        remember_check.pack(anchor=tk.W)
        
        # Bind Enter pour connexion
        self.email_entry.bind("<Return>", lambda e: self.password_entry.focus_set())
        self.password_entry.bind("<Return>", lambda e: self._on_login())
    
    def _create_actions(self, parent: ttk.Frame) -> None:
        """Créer les boutons d'action."""
        actions_frame = ttk.Frame(parent)
        actions_frame.pack(fill=tk.X, pady=(0, 20))
        
        # Bouton de connexion principal
        self.login_btn = ttk.Button(
            actions_frame,
            text="Se connecter",
            command=self._on_login,
            style="Accent.TButton"
        )
        self.login_btn.pack(fill=tk.X, pady=(0, 10))
        
        # Style personnalisé pour le bouton principal
        style = ttk.Style()
        style.configure(
            "Accent.TButton",
            background="#2563eb",
            foreground="white",
            font=("Arial", 11, "bold")
        )
        
        # Séparateur
        separator = ttk.Separator(actions_frame, orient=tk.HORIZONTAL)
        separator.pack(fill=tk.X, pady=(10, 10))
        
        # Boutons secondaires
        secondary_frame = ttk.Frame(actions_frame)
        secondary_frame.pack(fill=tk.X)
        
        # Créer un compte local
        create_local_btn = ttk.Button(
            secondary_frame,
            text="Créer un compte local",
            command=self._on_create_local_account
        )
        create_local_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # Mode hors ligne
        offline_btn = ttk.Button(
            secondary_frame,
            text="Mode hors ligne",
            command=self._on_offline_mode
        )
        offline_btn.pack(side=tk.RIGHT)
    
    def _create_footer(self, parent: ttk.Frame) -> None:
        """Créer le pied de page."""
        footer_frame = ttk.Frame(parent)
        footer_frame.pack(fill=tk.X, side=tk.BOTTOM)
        
        # Liens
        links_frame = ttk.Frame(footer_frame)
        links_frame.pack()
        
        forgot_link = ttk.Label(
            links_frame,
            text="Mot de passe oublié ?",
            foreground="#2563eb",
            cursor="hand2",
            font=("Arial", 9, "underline")
        )
        forgot_link.pack(side=tk.LEFT, padx=(0, 20))
        forgot_link.bind("<Button-1>", self._on_forgot_password)
        
        signup_link = ttk.Label(
            links_frame,
            text="Créer un compte cloud",
            foreground="#2563eb",
            cursor="hand2",
            font=("Arial", 9, "underline")
        )
        signup_link.pack(side=tk.RIGHT)
        signup_link.bind("<Button-1>", self._on_signup)
        
        # Version/Copyright
        version_label = ttk.Label(
            footer_frame,
            text="Web Sentinel v2.0 - Sécurité Web Intelligente",
            font=("Arial", 8),
            foreground="#9ca3af"
        )
        version_label.pack(pady=(10, 0))
    
    def _toggle_password_visibility(self) -> None:
        """Basculer la visibilité du mot de passe."""
        if self.show_password_var.get():
            self.password_entry.config(show="")
        else:
            self.password_entry.config(show="•")
    
    def _set_loading(self, loading: bool) -> None:
        """Activer/désactiver l'état de chargement."""
        self.is_loading = loading
        
        if loading:
            self.login_btn.config(text="Connexion en cours...", state="disabled")
            self.email_entry.config(state="disabled")
            self.password_entry.config(state="disabled")
            if self.window:
                self.window.config(cursor="wait")
        else:
            self.login_btn.config(text="Se connecter", state="normal")
            self.email_entry.config(state="normal")
            self.password_entry.config(state="normal")
            if self.window:
                self.window.config(cursor="")
    
    def _on_login(self) -> None:
        """Gérer la tentative de connexion."""
        if self.is_loading:
            return
        
        email = self.email_var.get().strip()
        password = self.password_var.get()
        remember = self.remember_var.get()
        
        # Validation
        if not email:
            messagebox.showerror("Erreur", "Veuillez saisir votre adresse email.")
            self.email_entry.focus_set()
            return
        
        if not password:
            messagebox.showerror("Erreur", "Veuillez saisir votre mot de passe.")
            self.password_entry.focus_set()
            return
        
        # Connexion en arrière-plan
        self._set_loading(True)
        
        def login_thread():
            try:
                success, error = self.auth_manager.login_email(email, password, remember)
                
                # Retour sur le thread principal
                if self.window:
                    self.window.after(0, lambda: self._on_login_result(success, error))
            except Exception as e:
                if self.window:
                    self.window.after(0, lambda: self._on_login_result(False, str(e)))
        
        threading.Thread(target=login_thread, daemon=True).start()
    
    def _on_login_result(self, success: bool, error: Optional[str]) -> None:
        """Traiter le résultat de la connexion."""
        self._set_loading(False)
        
        if success:
            self.result = True
            if self.on_success:
                self.on_success()
            if self.window:
                self.window.destroy()
        else:
            # Afficher l'erreur
            error_messages = {
                'invalid_credentials': 'Email ou mot de passe incorrect.',
                'user_not_found': 'Aucun compte trouvé avec cet email.',
                'invalid_password': 'Mot de passe incorrect.',
                'account_disabled': 'Compte désactivé. Contactez le support.',
                'network_error': 'Erreur réseau. Vérifiez votre connexion internet.',
                'user_exists': 'Un compte existe déjà avec cet email.'
            }
            
            message = error_messages.get(error, f'Erreur de connexion: {error}')
            messagebox.showerror("Erreur de connexion", message)
            
            # Focus selon le type d'erreur
            if error in ['user_not_found', 'user_exists']:
                self.email_entry.focus_set()
                self.email_entry.select_range(0, tk.END)
            else:
                self.password_entry.focus_set()
                self.password_entry.select_range(0, tk.END)
    
    def _on_create_local_account(self) -> None:
        """Créer un compte local."""
        dialog = CreateAccountDialog(self.window, self.auth_manager)
        if dialog.show():
            # Compte créé avec succès, connecter automatiquement
            email = dialog.email_var.get()
            password = dialog.password_var.get()
            
            # Remplir les champs et se connecter
            self.email_var.set(email)
            self.password_var.set(password)
            self.remember_var.set(True)
            self._on_login()
    
    def _on_offline_mode(self) -> None:
        """Basculer en mode hors ligne."""
        self.auth_manager.switch_to_offline_mode()
        self.result = True
        if self.on_success:
            self.on_success()
        if self.window:
            self.window.destroy()
    
    def _on_forgot_password(self, event=None) -> None:
        """Gérer le mot de passe oublié."""
        webbrowser.open("https://websentinel.dev/forgot-password")
    
    def _on_signup(self, event=None) -> None:
        """Rediriger vers l'inscription."""
        webbrowser.open("https://websentinel.dev/signup")
    
    def _on_cancel(self) -> None:
        """Annuler la connexion."""
        self.result = False
        if self.on_cancel:
            self.on_cancel()
        if self.window:
            self.window.destroy()


class CreateAccountDialog:
    """Dialogue de création de compte local."""
    
    def __init__(self, parent: tk.Widget, auth_manager: AuthManager):
        self.parent = parent
        self.auth_manager = auth_manager
        self.result = False
        self.window: Optional[tk.Toplevel] = None
        
        # Variables
        self.email_var = tk.StringVar()
        self.password_var = tk.StringVar()
        self.confirm_password_var = tk.StringVar()
        self.first_name_var = tk.StringVar()
        self.last_name_var = tk.StringVar()
    
    def show(self) -> bool:
        """Afficher le dialogue."""
        self._create_window()
        if self.window:
            self.window.wait_window()
        return self.result
    
    def _create_window(self) -> None:
        """Créer la fenêtre."""
        self.window = tk.Toplevel(self.parent)
        self.window.title("Créer un compte local")
        self.window.geometry("400x500")
        self.window.resizable(False, False)
        self.window.transient(self.parent)
        self.window.grab_set()
        
        # Centrer
        self.window.update_idletasks()
        x = (self.window.winfo_screenwidth() // 2) - (400 // 2)
        y = (self.window.winfo_screenheight() // 2) - (500 // 2)
        self.window.geometry(f"400x500+{x}+{y}")
        
        main_frame = ttk.Frame(self.window, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # Titre
        title_label = ttk.Label(
            main_frame,
            text="Créer un compte local",
            font=("Arial", 16, "bold")
        )
        title_label.pack(pady=(0, 20))
        
        # Formulaire
        form_frame = ttk.LabelFrame(main_frame, text="Informations", padding="15")
        form_frame.pack(fill=tk.X, pady=(0, 20))
        
        # Prénom
        ttk.Label(form_frame, text="Prénom :").pack(anchor=tk.W, pady=(0, 5))
        first_name_entry = ttk.Entry(form_frame, textvariable=self.first_name_var)
        first_name_entry.pack(fill=tk.X, pady=(0, 10))
        
        # Nom
        ttk.Label(form_frame, text="Nom :").pack(anchor=tk.W, pady=(0, 5))
        last_name_entry = ttk.Entry(form_frame, textvariable=self.last_name_var)
        last_name_entry.pack(fill=tk.X, pady=(0, 10))
        
        # Email
        ttk.Label(form_frame, text="Email :").pack(anchor=tk.W, pady=(0, 5))
        email_entry = ttk.Entry(form_frame, textvariable=self.email_var)
        email_entry.pack(fill=tk.X, pady=(0, 10))
        
        # Mot de passe
        ttk.Label(form_frame, text="Mot de passe :").pack(anchor=tk.W, pady=(0, 5))
        password_entry = ttk.Entry(form_frame, textvariable=self.password_var, show="•")
        password_entry.pack(fill=tk.X, pady=(0, 10))
        
        # Confirmation
        ttk.Label(form_frame, text="Confirmer le mot de passe :").pack(anchor=tk.W, pady=(0, 5))
        confirm_entry = ttk.Entry(form_frame, textvariable=self.confirm_password_var, show="•")
        confirm_entry.pack(fill=tk.X, pady=(0, 10))
        
        # Note sécurité
        note_label = ttk.Label(
            form_frame,
            text="Note: Le compte sera stocké localement sur cet appareil.",
            font=("Arial", 9),
            foreground="#6b7280"
        )
        note_label.pack(pady=(5, 0))
        
        # Boutons
        buttons_frame = ttk.Frame(main_frame)
        buttons_frame.pack(fill=tk.X)
        
        cancel_btn = ttk.Button(buttons_frame, text="Annuler", command=self._on_cancel)
        cancel_btn.pack(side=tk.RIGHT, padx=(10, 0))
        
        create_btn = ttk.Button(buttons_frame, text="Créer le compte", command=self._on_create)
        create_btn.pack(side=tk.RIGHT)
        
        # Focus
        first_name_entry.focus_set()
        
        # Gérer fermeture
        self.window.protocol("WM_DELETE_WINDOW", self._on_cancel)
    
    def _on_create(self) -> None:
        """Créer le compte."""
        # Validation
        if not self.email_var.get().strip():
            messagebox.showerror("Erreur", "Veuillez saisir votre email.")
            return
        
        if not self.password_var.get():
            messagebox.showerror("Erreur", "Veuillez saisir un mot de passe.")
            return
        
        if self.password_var.get() != self.confirm_password_var.get():
            messagebox.showerror("Erreur", "Les mots de passe ne correspondent pas.")
            return
        
        if len(self.password_var.get()) < 6:
            messagebox.showerror("Erreur", "Le mot de passe doit contenir au moins 6 caractères.")
            return
        
        # Créer le compte
        success, error = self.auth_manager.register_local_user(
            email=self.email_var.get().strip(),
            password=self.password_var.get(),
            first_name=self.first_name_var.get().strip(),
            last_name=self.last_name_var.get().strip()
        )
        
        if success:
            messagebox.showinfo("Succès", "Compte créé avec succès !")
            self.result = True
            self.window.destroy()
        else:
            error_messages = {
                'user_exists': 'Un compte existe déjà avec cet email.'
            }
            message = error_messages.get(error, f'Erreur: {error}')
            messagebox.showerror("Erreur", message)
    
    def _on_cancel(self) -> None:
        """Annuler."""
        self.result = False
        self.window.destroy()