<?PHP
namespace Classe;

use views\LoginHtml;
use Classe\Users;

use Classe\Visiteurs;
use Exception;

class Login
{
    public bool $userConnected = false;
    public string $page;

    public string $connectedHost;
    public string $sharedMessage;

    public function __construct(private $conn, string $v_page = "")
    {
        include_once("FunctionClasse.php");
        include("Parametre/" . getPath(1) . "/" . getPath(1) . ".php");
        
        $connectedHost = $this->getClientHostname();
        $this->sharedMessage = '';
        
        // Vérifier d'abord si une session existe déjà
        if (!isset($_SESSION[$NomSite]['userConnected']) || !$_SESSION[$NomSite]['userConnected']) {
            // Pas de session active, vérifier les cookies "Se souvenir de moi"
            $this->checkRememberMeCookies();
        }
        
        //$connectedHost = "ORDI TEST";

        //if ($connectedHost == "drht41201" || $connectedHost == "192.168.1.138") {
        //$v_page = "hv";
        //}

        switch ($v_page) {
            case "hv":
                $this->afficheHomeVisiteur();
                break;
            case "log":
                $this->afficheLogin($this->sharedMessage);
                break;
            case "lsl":
                // Traiter la soumission du formulaire de connexion
                $this->processLogin();
                break;
            case "d":
                $this->deconnection();
                break;
            default:
                if ($v_page != 'error')
                    $this->loginCheck($v_page);
        }
    }

    function deconnection()
    {
        include_once("FunctionClasse.php");
        include("Parametre/" . getPath(1) . "/" . getPath(1) . ".php");
        
        // Supprimer les cookies "Se souvenir de moi"
        $this->clearRememberMeCookies();
        
        // Supprimer le token de la base de données
        if (isset($_SESSION[$NomSite]['idUser'])) {
            try {
                // Vérifier si les colonnes existent avant de les utiliser
                $checkColumnSql = "SHOW COLUMNS FROM users LIKE 'remember_token'";
                $this->conn->exec($checkColumnSql);
                $columnExists = !empty($this->conn->getData());
                
                if ($columnExists) {
                    $userId = (int)$_SESSION[$NomSite]['idUser'];
                    $sql = "UPDATE users SET remember_token = NULL, remember_expires = NULL WHERE id = ?";
                    $stmt = $this->conn->prepare($sql);
                    if ($stmt) {
                        $stmt->bind_param('i', $userId);
                        $stmt->execute();
                        $stmt->close();
                    }
                }
            } catch (Exception $e) {
                // Ignorer silencieusement si les colonnes n'existent pas
                error_log("Could not clear remember token: " . $e->getMessage());
            }
        }
        
        unset($_SESSION[$NomSite]);
        
        // Redirection intelligente vers la page de connexion
        $currentPath = $_SERVER['REQUEST_URI'];
        if (strpos($currentPath, '/admin/') !== false) {
            header("Location: index.php?page=log");
        } else if (strpos($currentPath, '/visiteur/') !== false) {
            header("Location: index.php?page=log");
        } else {
            header("Location: admin/index.php?page=log");
        }
    }

    private function processLogin()
    {
        include_once("FunctionClasse.php");
        include("Parametre/" . getPath(1) . "/" . getPath(1) . ".php");

        if (!isset($_POST["user"]) || !isset($_POST["password"])) {
            $this->sharedMessage = "Nom d'utilisateur et mot de passe requis.";
            $this->afficheLogin($this->sharedMessage);
            return;
        }

        $username = trim($_POST["user"]);
        $password = $_POST["password"];

        if (empty($username) || empty($password)) {
            $this->sharedMessage = "Nom d'utilisateur et mot de passe requis.";
            $this->afficheLogin($this->sharedMessage);
            return;
        }

        try {
            // Échapper les données pour la sécurité
            $escapedUsername = $this->conn->escape($username);
            
            // Requête pour vérifier l'utilisateur avec la nouvelle structure
            $sql = "SELECT u.id, u.username, u.email, u.password, u.actif, r.nom_role, r.niveau_acces 
                    FROM users u 
                    INNER JOIN roles r ON u.role_id = r.id 
                    WHERE (u.username = '$escapedUsername' OR u.email = '$escapedUsername') AND u.actif = 1";
            
            $this->conn->exec($sql);
            $users = $this->conn->getData();

            if (!empty($users) && password_verify($password, $users[0]['password'])) {
                // Connexion réussie
                $user = $users[0];
                $_SESSION[$NomSite]['idUser'] = $user['id'];
                $_SESSION[$NomSite]['username'] = $user['username'];
                $_SESSION[$NomSite]['email'] = $user['email'];
                $_SESSION[$NomSite]['role'] = $user['nom_role'];
                $_SESSION[$NomSite]['niveau_acces'] = $user['niveau_acces'];
                $_SESSION[$NomSite]['userConnected'] = true;
                $_SESSION[$NomSite]['lastActivityTime'] = time();
                
                // Gestion de "Se souvenir de moi"
                if (isset($_POST['rememberMe']) && $_POST['rememberMe'] == '1') {
                    try {
                        // Vérifier si les colonnes existent avant de les utiliser
                        $checkColumnSql = "SHOW COLUMNS FROM users LIKE 'remember_token'";
                        $this->conn->exec($checkColumnSql);
                        $columnExists = !empty($this->conn->getData());
                        
                        if ($columnExists) {
                            // Créer un token unique pour ce user
                            $rememberToken = bin2hex(random_bytes(32));
                            
                            // Stocker le token en base de données (durée 30 jours)
                            $expireTime = time() + (30 * 24 * 60 * 60); // 30 jours
                            $updateTokenSql = "UPDATE users SET remember_token = ?, remember_expires = FROM_UNIXTIME(?) WHERE id = ?";
                            $stmt = $this->conn->prepare($updateTokenSql);
                            if ($stmt) {
                                $stmt->bind_param('sii', $rememberToken, $expireTime, $user['id']);
                                $stmt->execute();
                                $stmt->close();
                                
                                // Créer les cookies (30 jours)
                                setcookie('taghilt_remember_user', $user['id'], $expireTime, '/', '', false, true);
                                setcookie('taghilt_remember_token', $rememberToken, $expireTime, '/', '', false, true);
                            }
                        }
                    } catch (Exception $e) {
                        // Ignorer silencieusement si les colonnes n'existent pas encore
                        error_log("Remember me feature not available: " . $e->getMessage());
                    }
                }
                
                // Mettre à jour la dernière connexion
                $updateSql = "UPDATE users SET derniere_connexion = NOW() WHERE id = " . (int)$user['id'];
                $this->conn->exec($updateSql);
                
                $this->userConnected = true;
                
                // Déterminer la redirection selon le contexte
                $currentPath = $_SERVER['REQUEST_URI'];
                if (strpos($currentPath, '/admin/') !== false) {
                    header("Location: index.php");
                } else if (strpos($currentPath, '/visiteur/') !== false) {
                    header("Location: index.php");
                } else {
                    header("Location: admin/index.php");
                }
                exit;
            } else {
                $this->sharedMessage = "Nom d'utilisateur ou mot de passe incorrect.";
                $this->afficheLogin($this->sharedMessage);
            }
        } catch (Exception $e) {
            error_log("Erreur de connexion: " . $e->getMessage());
            $this->sharedMessage = "Erreur lors de la connexion. Veuillez réessayer.";
            $this->afficheLogin($this->sharedMessage);
        }
    }

    static public function getClientHostname()
    {
        $hostname = strtoupper(gethostbyaddr($_SERVER['REMOTE_ADDR']));
        $hostname = str_replace(".drht.LOCAL", "", $hostname);
        $hostname = str_replace(".drht.RTSS.QC.CA", "", $hostname);
        return $hostname;
    }
    private function loginCheck($nomPage)
    {
        include_once("FunctionClasse.php");
        include("Parametre/" . getPath(1) . "/" . getPath(1) . ".php");

        $conn = $this->conn;
        $sharedMessage = '';

        if (empty($_SESSION[$NomSite]['idUser'])) {
            $this->afficheLogin($this->sharedMessage);
            // header("Location:/".$NomSite."/admin/index.php?page=log");
        } elseif (isset($_SESSION[$NomSite]['lastActivityTime']) & ((time() - $_SESSION[$NomSite]['lastActivityTime'])) > $timeLimit) {
            // déconnexion automatique après le délai demande de se connecter a nouveau
            unset($_SESSION[$NomSite]['userConnected']);
            unset($_SESSION[$NomSite]['idUser']);
            unset($_SESSION[$NomSite]['lastActivityTime']);
            $_SESSION[$NomSite]['lastPage'] = $_SERVER['REQUEST_URI'];
            $this->afficheLogin($sharedMessage);
        } else {
            $idUser = $_SESSION[$NomSite]['idUser'];
            $_SESSION[$NomSite]['userConnected'] = true;
            $_SESSION[$NomSite]['AllowAccessTabVisitor'] = true;
            $_SESSION[$NomSite]['AllowAddVisitor'] = true;
            $_SESSION[$NomSite]['AllowEditVisitor'] = true;
            $_SESSION[$NomSite]['AllowDeleteVisitor'] = true;

            if (!isset($_SESSION[$NomSite]['lastActivityTime']))
                $_SESSION[$NomSite]['lastActivityTime'] = 0;
            $user = new Users($conn, $idUser);
            if ($nomPage == "")
                $nomPage = "admin/index.php";

            // TODO: Classe Page manquante - système de permissions simplifié temporairement
            // $page = new Page($conn);
            // $idUrl = $page->getUrl($nomPage);
            // $authorisation = $page->valideRole($idUrl, $idUser);

            // Vérifier si le contrat est terminé
            // if (!empty($user->valideContrat()))
            //     $authorisation = 0;

            $authorisation = 25; // Accès autorisé par défaut
            // Regarde si l'usager a le droit d'accès à la page
            if ($authorisation >= 1) {
                $lastPage = $_SERVER['REQUEST_URI'];
                $_SESSION[$NomSite]['lastPage'] = $lastPage;
                $_SESSION[$NomSite]['lastActivityTime'] = time();

                // Récupération des rôles utilisateur avec le nouveau système
                $userRoles = $user->getUserRoles($idUser);
                $_SESSION[$NomSite]['userRoles'] = $userRoles;

                // Vérification des permissions pour les pages protégées
                $this->checkPagePermissions($nomPage, $userRoles, $NomSite);

                if (empty($_SESSION['csrf_token'])) {
                    $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); // secure token
                }
                //update de la bd
                $lastTime = date("Y-m-d H:i:s");
                $lastHost = Login::getClientHostname();
                $user->setUserAccesPage($lastPage, $idUser, $lastTime, $lastHost );
                // TODO: Classe Page manquante - setPageViews désactivé temporairement
                // if ($idUser != 1) // authse
                // {
                //     $page->setPageViews($idUser, $idUrl, $lastPage, $lastHost);
                // }
                $this->userConnected = true;
            } else {
                if ($idUser == 11) {
                    echo 'idUser = ' . $idUser . '<br>';
                    echo 'nomPage = ' . $nomPage . '<br>';
                }
                //pas le droit affiche une fenettre d'avertisement
                header("Location:/" . $NomSite . "/accessDenied.php");
            }
        }
    }
    
    private function afficheLogin($sharedMessage)
    {
        include("Parametre/" . getPath(1) . "/" . getPath(1) . ".php");
        if (!$SiteEnMaintenance || ($SiteEnMaintenance && in_array($connectedHost, $AllowedMachineOnMaintenance)))
            LoginHtml::afficheLogin($sharedMessage);
    }
    private function afficheHomeVisiteur()
    {
        $visiteurs = new Visiteurs();
        $visiteurs->afficheHomeVisiteur($this->conn);
    }

    /**
     * Vérifier les permissions pour les pages protégées
     * @param string $nomPage - Le nom de la page demandée
     * @param array $userRoles - Les rôles de l'utilisateur
     * @param string $NomSite - Le nom du site pour les sessions
     */
    private function checkPagePermissions($nomPage, $userRoles, $NomSite)
    {
        // Extraire le paramètre 'page' de l'URL
        $page = $_GET['page'] ?? '';
        
        // Définir les niveaux d'accès requis pour chaque page protégée
        $protectedPages = [
            'user' => 40,  // Gestion utilisateurs - Agent Standard ou plus
            'role' => 80,  // Gestion rôles - Administrateur ou plus
            'wdw' => 60    // Who did what - Modérateur ou plus
        ];

        // Vérifier si la page demandée est protégée
        if (isset($protectedPages[$page])) {
            $requiredLevel = $protectedPages[$page];
            
            // Calculer le niveau maximum de l'utilisateur
            $userMaxLevel = 0;
            foreach ($userRoles as $role) {
                if (isset($role['niveau_acces'])) {
                    $userMaxLevel = max($userMaxLevel, (int)$role['niveau_acces']);
                }
                
                // Compatibilité avec l'ancien système de noms de rôles
                if (isset($role['role_name'])) {
                    switch ($role['role_name']) {
                        case 'Super Administrateur':
                            $userMaxLevel = max($userMaxLevel, 100);
                            break;
                        case 'Administrateur':
                            $userMaxLevel = max($userMaxLevel, 80);
                            break;
                        case 'Modérateur':
                            $userMaxLevel = max($userMaxLevel, 60);
                            break;
                        case 'Agent Premium':
                            $userMaxLevel = max($userMaxLevel, 50);
                            break;
                        case 'Agent Standard':
                            $userMaxLevel = max($userMaxLevel, 40);
                            break;
                        case 'Particulier':
                            $userMaxLevel = max($userMaxLevel, 20);
                            break;
                        case 'Visiteur':
                            $userMaxLevel = max($userMaxLevel, 10);
                            break;
                    }
                }
            }

            // Si l'utilisateur n'a pas le niveau requis, afficher la page d'accès refusé
            if ($userMaxLevel < $requiredLevel) {
                // Sauvegarder la page tentée
                $_SESSION[$NomSite]['lastPage'] = $_SERVER['REQUEST_URI'];
                
                // Afficher directement la page d'accès refusé
                $this->showAccessDeniedPage($requiredLevel);
                exit();
            }
        }
    }

    /**
     * Affiche directement la page d'accès refusé sans redirection
     */
    private function showAccessDeniedPage($requiredLevel)
    {
        // Inclure les classes nécessaires
        include_once(__DIR__ . "/../views/VariousViewsHtml.php");
        include_once(__DIR__ . "/../Classe/FunctionClasse.php");
        include(__DIR__ . "/../Parametre/" . getPath(1) . "/" . getPath(1) . ".php");
        
        // Récupérer les informations de l'utilisateur
        global $NomSite, $NomSiteCap;
        $userRole = '';
        
        if (isset($_SESSION[$NomSite]['userRoles']) && !empty($_SESSION[$NomSite]['userRoles'])) {
            $roles = $_SESSION[$NomSite]['userRoles'];
            $roleNames = array_map(function($role) {
                return $role['role_name'] ?? 'Inconnu';
            }, $roles);
            $userRole = implode(', ', $roleNames);
        }
        
        // Afficher la page d'accès refusé
        $variousViews = new \Views\VariousViewsHtml();
        $variousViews->generateHeader(false, false, "Accès refusé - " . $NomSiteCap, "normal");
        $variousViews->showAccessDenied($userRole, (int)$requiredLevel);
        
        // Script de redirection automatique
        $lastPage = $_SESSION[$NomSite]['lastPage'] ?? 'admin/index.php';
        echo "<script>
        setTimeout(function() {
            window.location.href = '$lastPage';
        }, 5000);
        </script>";
        
        $variousViews->generateFooter(false, false, "normal");
    }
    
    /**
     * Vérifier et traiter les cookies "Se souvenir de moi"
     */
    private function checkRememberMeCookies()
    {
        include_once("FunctionClasse.php");
        include("Parametre/" . getPath(1) . "/" . getPath(1) . ".php");
        
        // Vérifier si les cookies existent
        if (!isset($_COOKIE['taghilt_remember_user']) || !isset($_COOKIE['taghilt_remember_token'])) {
            return false;
        }
        
        try {
            // Vérifier si les colonnes remember_token existent
            $checkColumnSql = "SHOW COLUMNS FROM users LIKE 'remember_token'";
            $this->conn->exec($checkColumnSql);
            $columnExists = !empty($this->conn->getData());
            
            if (!$columnExists) {
                // Les colonnes n'existent pas encore, supprimer les cookies
                $this->clearRememberMeCookies();
                return false;
            }
            
            $userId = (int)$_COOKIE['taghilt_remember_user'];
            $token = $_COOKIE['taghilt_remember_token'];
            
            // Vérifier le token en base de données
            $sql = "SELECT u.id, u.username, u.email, u.actif, u.remember_token, u.remember_expires, 
                           r.nom_role, r.niveau_acces 
                    FROM users u 
                    INNER JOIN roles r ON u.role_id = r.id 
                    WHERE u.id = ? AND u.remember_token = ? AND u.actif = 1 
                    AND u.remember_expires > NOW()";
            
            $stmt = $this->conn->prepare($sql);
            if ($stmt) {
                $stmt->bind_param('is', $userId, $token);
                $stmt->execute();
                $result = $stmt->get_result();
                
                if ($result && $result->num_rows > 0) {
                    $user = $result->fetch_assoc();
                    
                    // Restaurer la session utilisateur
                    $_SESSION[$NomSite]['idUser'] = $user['id'];
                    $_SESSION[$NomSite]['username'] = $user['username'];
                    $_SESSION[$NomSite]['email'] = $user['email'];
                    $_SESSION[$NomSite]['role'] = $user['nom_role'];
                    $_SESSION[$NomSite]['niveau_acces'] = $user['niveau_acces'];
                    $_SESSION[$NomSite]['userConnected'] = true;
                    $_SESSION[$NomSite]['lastActivityTime'] = time();
                    
                    // Mettre à jour la dernière connexion
                    $updateSql = "UPDATE users SET derniere_connexion = NOW() WHERE id = ?";
                    $updateStmt = $this->conn->prepare($updateSql);
                    if ($updateStmt) {
                        $updateStmt->bind_param('i', $user['id']);
                        $updateStmt->execute();
                        $updateStmt->close();
                    }
                    
                    $this->userConnected = true;
                    $stmt->close();
                    return true;
                } else {
                    // Token invalide ou expiré, supprimer les cookies
                    $this->clearRememberMeCookies();
                }
                $stmt->close();
            }
        } catch (Exception $e) {
            // En cas d'erreur, supprimer les cookies
            $this->clearRememberMeCookies();
            error_log("Error checking remember me cookies: " . $e->getMessage());
        }
        
        return false;
    }
    
    /**
     * Supprimer les cookies "Se souvenir de moi"
     */
    private function clearRememberMeCookies()
    {
        setcookie('taghilt_remember_user', '', time() - 3600, '/', '', false, true);
        setcookie('taghilt_remember_token', '', time() - 3600, '/', '', false, true);
    }
}
