
    q=hX                        d dl mZmZmZmZmZmZ d dlmZm	Z	m
Z
mZmZmZmZ d dl mZmZmZmZ d dlmZmZmZmZmZ d dlmZ  ede      Z ee      Zde_        dZej9                  d	      d
        Zej9                  d      d        Zej9                  d      d        Zej9                  d      d        Z ej9                  d      d        Z!ej9                  d      d        Z"ej9                  d      d        Z#ej9                  d      d        Z$ej9                  d      d        Z%ej9                  d      d        Z&ej9                  d      d        Z'ejQ                  d      d         Z)ejT                  d!        Z+ej9                  d"d#g$      d%        Z,ej9                  d&d#g$      d'        Z-ej9                  d(d#g$      d)        Z.ej9                  d*d+g$      ed,               Z/d d-lmZm
Z
 d d.l mZmZ ej9                  d/d#g$      ed0               Z0ej9                  d/d+g$      ed1               Z1ej9                  d/d2g$      ed3               Z2ej9                  d4d+g$      ed5               Z3ej9                  d6      d7        Z4ej9                  d8      d9        Z5ej9                  d:d+g$      d;        Z6ej9                  d<d+g$      d=        Z7d d-lmZm
Z
 ej9                  d>      d?        Z8y@)A    )LoginManager	UserMixin
login_userlogin_requiredlogout_usercurrent_user)	Blueprintrender_template_stringrequestjsonifyflashredirecturl_for)r   r   r   r   )UserCityDistrictget_db_connectionbcrypt)geodesicroutesloginu\  
<!DOCTYPE html>
<html lang="fr" data-theme="light">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Map Immobilier</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/awesomplete@1.1.5/awesomplete.css" />
    <link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.css" />
    <link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.Default.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
    <link rel="stylesheet" href="/static/styles.css" />
</head>
<body>
    <div class="header">
        <div class="menu-container">
            <div class="menu">
                <!-- Bouton toggle (mobile seulement) -->
                <button class="menu-toggle" id="menuToggle" aria-label="Ouvrir/Fermer le menu">
                    <i class="fas fa-bars"></i>
                </button>

                <!-- Menu principal -->
                <div class="menu-content" id="menuContent">
                    <div class="menu-header">
                        <h1 class="title logo" id="homeLink">Immo</h1>
                        <div class="search-box-container">
                            <i class="fas fa-search search-icon"></i>
                            <input
                                type="text"
                                class="search-box"
                                id="searchBox"
                                placeholder="Rechercher une région, ville, quartier"
                                aria-label="Rechercher"
                            />
                        </div>
                    </div>

                    <div class="menu-items">
                        <a href="#" class="menu-item" id="filters"><i class="fa-solid fa-filter primary-text"></i> Filtres</a>
                            {% if current_user.is_authenticated %}
                                <a href="#" onclick="openAccountModal()" class="menu-item">
                                    <i class="fa-solid fa-user primary-text"></i> {{ current_user.first_name or 'Mon Compte' }}
                                </a>
                            {% else %}
                                <a href="#" onclick="openLoginModal()" class="menu-item">
                                    <i class="fa-solid fa-right-to-bracket primary-text"></i> Connexion
                                </a>
                            {% endif %}                        
                            <button class="theme-toggle" id="themeToggle" aria-label="Changer de thème">
                            <i class="fas fa-sun theme-icon primary-text"></i>
                        </button>
                    </div>
                </div>

                <!-- Overlay pour fermer le menu (mobile) -->
                <div id="overlay" class="overlay"></div>
            </div>
        </div>
    </div>
    <div id="map"></div>
    <div class="overlay" id="overlay"></div>
    <div id="filterPanel" class="filter-panel">
        <div class="info-panel-header">
            <h3><i class="fas fa-filter"></i> Filtres</h3>
            <button id="closeFilterPanel" class="close-panel">&times;</button>
        </div>
        <div class="info-panel-content">
            <div class="filter-section">
                <h4><i class="fas fa-subway"></i> Transports en commun</h4>
                <select id="transportFilter" class="filter-select">
                    <option value="">Tous</option>
                    <option value="metro">Métro</option>
                    <option value="tram">Tramway</option>
                    <option value="bus">Bus</option>
                </select>
            </div>
            <div class="filter-section">
                <h4><i class="fas fa-heart"></i> Qualité de vie</h4>
                <select id="qualityFilter" class="filter-select">
                    <option value="">Tous</option>
                    <option value="high">Élevée</option>
                    <option value="medium">Moyenne</option>
                    <option value="low">Faible</option>
                </select>
            </div>
            <div class="filter-section">
                <h4><i class="fas fa-shield-alt"></i> Sécurité</h4>
                <select id="safetyFilter" class="filter-select">
                    <option value="">Tous</option>
                    <option value="safe">Sûr</option>
                    <option value="medium">Moyen</option>
                    <option value="unsafe">Peu sûr</option>
                </select>
            </div>
            <div class="filter-section">
                <h4><i class="fas fa-euro-sign"></i> Prix au m² (max)</h4>
                <div class="price-range-container">
                    <input type="range" id="priceRange" min="0" max="10000" step="100" value="10000" class="price-range">
                    <span id="priceValue" class="price-value">10 000 €/m²</span>
                </div>
            </div>
            <button id="applyFilters" class="apply-filters-btn">Appliquer les filtres</button>
        </div>
    </div>
    <div id="infoPanel" class="info-panel">
        <div class="info-panel-header">
            <h3 id="infoPanelTitle">Informations</h3>
            <button id="closeInfoPanel" class="close-panel-button">
                <i class="fas fa-times"></i>
            </button>
        </div>
        <div id="infoPanelContent" class="info-panel-content">
            <!-- Contenu dynamique -->
        </div>
    </div>

    <div id="price-legend">
        <div><span style="color: #e74c3c;font-size:20px;vertical-align: sub;">■</span> Très cher (> 5 000 €/m²)</div>
        <div><span style="color: #f39c12;font-size:20px;vertical-align: sub;">■</span> Cher (3 000–5 000 €/m²)</div>
        <div><span style="color: #f1c40f;font-size:20px;vertical-align: sub;">■</span> Moyen (2 000–3 000 €/m²)</div>
        <div><span style="color: #27ae60;font-size:20px;vertical-align: sub;">■</span> Abordable (< 2 000 €/m²)</div>
    </div>
<!-- Modale pour Login -->
<div id="loginModal" class="modal">
    <div class="modal-content">
        <span class="close-modal">&times;</span>
        <h2><i class="fas fa-sign-in-alt"></i> Connexion</h2>
        <form id="loginForm" method="POST" action="/login">
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
            <div class="form-group">
                <label for="loginEmail">Email</label>
                <input type="email" id="loginEmail" name="email" class="form-control" placeholder="Votre email" required>
            </div>
            <div class="form-group">
                <label for="loginPassword">Mot de passe</label>
                <input type="password" id="loginPassword" name="password" class="form-control" placeholder="Votre mot de passe" required>
            </div>
            <div class="form-group form-check">
                <input type="checkbox" id="rememberMe" name="remember_me" class="form-check-input">
                <label for="rememberMe" class="form-check-label">Se souvenir de moi</label>
            </div>
            <button type="submit" class="btn btn-primary btn-block">Se connecter</button>
        </form>
        <div class="mt-3 text-center">
            <p>Pas encore de compte ? <a href="#" onclick="openRegisterModal()">Inscrivez-vous ici</a>.</p>
        </div>
    </div>
</div>

<!-- Modale pour Register -->
<div id="registerModal" class="modal">
    <div class="modal-content">
        <span class="close-modal">&times;</span>
        <h2><i class="fas fa-user-plus"></i> Inscription</h2>
        <form id="registerForm" method="POST" action="/register">
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
            <div class="form-group">
                <label for="registerEmail">Email</label>
                <input type="email" id="registerEmail" name="email" class="form-control" placeholder="Votre email" required>
            </div>
            <div class="form-group">
                <label for="registerPassword">Mot de passe</label>
                <input type="password" id="registerPassword" name="password" class="form-control" placeholder="Votre mot de passe" required>
            </div>
            <div class="form-group">
                <label for="confirmPassword">Confirmer le mot de passe</label>
                <input type="password" id="confirmPassword" name="confirm_password" class="form-control" placeholder="Confirmez votre mot de passe" required>
            </div>
            <div class="form-group">
                <label for="accountType">Type de compte</label>
                <select id="accountType" name="account_type" class="form-control" required>
                    <option value="">Sélectionnez un type</option>
                    <option value="particulier">Particulier</option>
                    <option value="agent_immobilier">Agent immobilier</option>
                    <option value="investisseur">Investisseur</option>
                    <option value="autre">Autre</option>
                </select>
            </div>
            <div class="form-group">
                <label for="firstName">Prénom</label>
                <input type="text" id="firstName" name="first_name" class="form-control" placeholder="Votre prénom" required>
            </div>
            <div class="form-group">
                <label for="lastName">Nom</label>
                <input type="text" id="lastName" name="last_name" class="form-control" placeholder="Votre nom" required>
            </div>
            <div class="form-group form-check">
                <input type="checkbox" id="newsletterSubscription" name="newsletter_subscription" class="form-check-input">
                <label for="newsletterSubscription" class="form-check-label">S'abonner à la newsletter</label>
            </div>
            <button type="submit" class="btn btn-primary btn-block">S'inscrire</button>
        </form>
        <div class="mt-3 text-center">
            <p>Déjà un compte ? <a href="#" onclick="openLoginModal()">Connectez-vous ici</a>.</p>
        </div>
    </div>
</div>

    <!-- Modale pour Account -->
    <div id="accountModal" class="modal">
        <div class="modal-content">
            <span class="close-modal">&times;</span>
            <h2><i class="fas fa-user"></i> Mon Compte</h2>
            <div id="accountInfo">
                <!-- Les informations du compte seront chargées ici via JavaScript -->
                <p><strong>Email :</strong> <span id="userEmail"></span></p>
                <p><strong>Type de compte :</strong> <span id="userAccountType"></span></p>
                <p><strong>Prénom :</strong> <span id="userFirstName"></span></p>
                <p><strong>Nom :</strong> <span id="userLastName"></span></p>
            </div>
            <div class="mt-4">
                <button id="logoutButton" class="btn btn-danger">Déconnexion</button>
            </div>
        </div>
    </div>
<!-- Modale pour Login -->
<div id="loginModal" class="modal">
    <div class="modal-content">
        <span class="close-modal">&times;</span>
        <h2><i class="fas fa-sign-in-alt"></i> Connexion</h2>
        <form id="loginForm" method="POST">
            <div class="form-group">
                <label for="loginEmail">Email</label>
                <input type="email" id="loginEmail" name="email" class="form-control" placeholder="Votre email" required>
            </div>
            <div class="form-group">
                <label for="loginPassword">Mot de passe</label>
                <input type="password" id="loginPassword" name="password" class="form-control" placeholder="Votre mot de passe" required>
            </div>
            <div class="form-group form-check">
                <input type="checkbox" id="rememberMe" name="remember_me" class="form-check-input">
                <label for="rememberMe" class="form-check-label">Se souvenir de moi</label>
            </div>
            <button type="submit" class="btn btn-primary btn-block">Se connecter</button>
        </form>
        <div class="mt-3 text-center">
            <p>Pas encore de compte ? <a href="#" onclick="openRegisterModal()">Inscrivez-vous ici</a>.</p>
        </div>
    </div>
</div>

<!-- Modale pour Register -->
<div id="registerModal" class="modal">
    <div class="modal-content">
        <span class="close-modal">&times;</span>
        <h2><i class="fas fa-user-plus"></i> Inscription</h2>
        <form id="registerForm" method="POST" action="/register">
            <div class="form-group">
                <label for="registerEmail">Email</label>
                <input type="email" id="registerEmail" name="email" class="form-control" placeholder="Votre email" required>
            </div>
            <div class="form-group">
                <label for="registerPassword">Mot de passe</label>
                <input type="password" id="registerPassword" name="password" class="form-control" placeholder="Votre mot de passe" required>
            </div>
            <div class="form-group">
                <label for="confirmPassword">Confirmer le mot de passe</label>
                <input type="password" id="confirmPassword" name="confirm_password" class="form-control" placeholder="Confirmez votre mot de passe" required>
            </div>
            <div class="form-group">
                <label for="accountType">Type de compte</label>
                <select id="accountType" name="account_type" class="form-control" required>
                    <option value="">Sélectionnez un type</option>
                    <option value="particulier">Particulier</option>
                    <option value="agent_immobilier">Agent immobilier</option>
                    <option value="investisseur">Investisseur</option>
                    <option value="autre">Autre</option>
                </select>
            </div>
            <div class="form-group">
                <label for="firstName">Prénom</label>
                <input type="text" id="firstName" name="first_name" class="form-control" placeholder="Votre prénom" required>
            </div>
            <div class="form-group">
                <label for="lastName">Nom</label>
                <input type="text" id="lastName" name="last_name" class="form-control" placeholder="Votre nom" required>
            </div>
            <div class="form-group form-check">
                <input type="checkbox" id="newsletterSubscription" name="newsletter_subscription" class="form-check-input">
                <label for="newsletterSubscription" class="form-check-label">S'abonner à la newsletter</label>
            </div>
            <button type="submit" class="btn btn-primary btn-block">S'inscrire</button>
        </form>
        <div class="mt-3 text-center">
            <p>Déjà un compte ? <a href="#" onclick="openLoginModal()">Connectez-vous ici</a>.</p>
        </div>
    </div>
</div>

<!-- Modale pour Account -->
<div id="accountModal" class="modal">
    <div class="modal-content">
        <span class="close-modal">&times;</span>
        <h2><i class="fas fa-user"></i> Mon Compte</h2>
        <div id="accountInfo">
            <!-- Les informations du compte seront chargées ici via JavaScript -->
            <p><strong>Email :</strong> <span id="userEmail"></span></p>
            <p><strong>Type de compte :</strong> <span id="userAccountType"></span></p>
            <p><strong>Prénom :</strong> <span id="userFirstName"></span></p>
            <p><strong>Nom :</strong> <span id="userLastName"></span></p>
        </div>
        <div class="mt-4">
            <button id="logoutButton" class="btn btn-danger">Déconnexion</button>
        </div>
    </div>
</div>

    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
    <script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
    <script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/awesomplete@1.1.5/awesomplete.min.js"></script>
    <script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/qrcodejs/qrcode.min.js"></script>

    <script>
        // Passe les variables Jinja vers JavaScript
        window.currentUser = {
            id: {{ current_user.id if current_user.is_authenticated else 'null' }},
            isAuthenticated: {{ 'true' if current_user.is_authenticated else 'false' }}
        };
    </script>
    <script src="/static/script.js"></script>
    <script>
    function logout() {
    fetch("/logout", {
        method: "POST",
        headers: {
            "Accept": "application/json",
            "X-CSRFToken": getCookie('csrf_token')
        }
    })
    .then(response => {
        if (!response.ok) {
            return response.json().then(err => { throw new Error(err.message); });
        }
        return response.json();
    })
    .then(data => {
        if (data.success) {
            alert("Vous avez été déconnecté.");
            closeModal("accountModal");
            window.location.reload();
        } else {
            alert("Erreur : " + data.message);
        }
    })
    .catch(error => {
        console.error("Erreur lors de la déconnexion :", error);
        alert("Erreur : " + error.message);
    });
}

    // Fonction pour récupérer le jeton CSRF depuis le cookie
    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }

    // Fonction pour envoyer une requête avec le jeton CSRF
    function fetchWithCSRF(url, options = {}) {
        const csrfToken = getCookie('csrf_token');
        if (!options.headers) {
            options.headers = {};
        }
        options.headers['X-CSRFToken'] = csrfToken;
        return fetch(url, options);
    }

    // Fonction pour ouvrir une modale
    function openModal(modalId) {
        document.getElementById(modalId).style.display = "block";
    }

    // Fonction pour fermer une modale
    function closeModal(modalId) {
        document.getElementById(modalId).style.display = "none";
    }

    // Fonctions spécifiques pour chaque modale
    function openLoginModal() {
        openModal("loginModal");
    }

    function openRegisterModal() {
        openModal("registerModal");
    }

    function openAccountModal() {
        // Charge les informations du compte via une requête AJAX
        fetch("/api/account")
            .then(response => response.json())
            .then(data => {
                if (data.logged_in) {
                    // Met à jour les informations dans la modale
                    document.getElementById("userEmail").textContent = data.email;
                    document.getElementById("userAccountType").textContent = data.account_type;
                    document.getElementById("userFirstName").textContent = data.first_name;
                    document.getElementById("userLastName").textContent = data.last_name;
                    if (data.phone) {
                        document.getElementById("userPhone").textContent = data.phone;
                    }
                    // Ouvre la modale
                    openModal("accountModal");
                } else {
                    alert("Vous devez être connecté pour accéder à cette page.");
                    openLoginModal(); // Ouvre la modale de connexion si l'utilisateur n'est pas connecté
                }
            })
            .catch(error => {
                console.error("Erreur lors de la récupération des informations du compte :", error);
                alert("Une erreur est survenue. Veuillez réessayer.");
            });
    }


    // Fermer les modales en cliquant sur la croix
    document.querySelectorAll(".close-modal").forEach(span => {
        span.onclick = function() {
            this.parentElement.parentElement.style.display = "none";
        };
    });

    // Fermer les modales en cliquant en dehors de la modale
    window.onclick = function(event) {
        if (event.target.classList.contains("modal")) {
            event.target.style.display = "none";
        }
    };

    // Gérer la soumission des formulaires
document.getElementById("loginForm").onsubmit = function(event) {
    event.preventDefault();

    const formData = new FormData(this);

    fetchWithCSRF("/login", {
        method: "POST",
        body: formData,
        headers: {
            "Accept": "application/json",
        },
    })
    .then(response => {
        if (!response.ok) {
            return response.json().then(err => { throw new Error(err.message); });
        }
        return response.json();
    })
    .then(data => {
        if (data.success) {
            alert("Connexion réussie !");
            closeModal("loginModal");
            window.location.reload();
        } else {
            alert("Erreur : " + data.message);
        }
    })
    .catch(error => {
        console.error("Erreur lors de la connexion :", error);
        alert("Erreur : " + error.message);
    });
};



    document.getElementById("registerForm").onsubmit = function(event) {
        event.preventDefault();
        const formData = new FormData(this);
        fetch("/register", {
            method: "POST",
            body: formData
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                alert("Inscription réussie ! Vous pouvez maintenant vous connecter.");
                closeModal("registerModal");
                openLoginModal();
            } else {
                alert("Erreur : " + data.message);
            }
        })
        .catch(error => {
            console.error("Erreur lors de l'inscription :", error);
        });
    };

    // Gérer la déconnexion
    document.getElementById("logoutButton").onclick = function() {
        fetch("/logout", {
            method: "POST"
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                alert("Vous avez été déconnecté.");
                closeModal("accountModal");
            } else {
                alert("Erreur lors de la déconnexion.");
            }
        })
        .catch(error => {
            console.error("Erreur lors de la déconnexion :", error);
        });
    };
</script>

</body>
</html>/c                       t        t              S Nr
   html_content     /var/www/html/routes.pyhomer      s    !,//r   z/searchc                  h   t         j                  j                  dd      j                         } | st	        g       S t               }|j                  d      }|j                  dd|  dd|  df       |j                         }|j                  dd|  df       |j                         }|j                  dd|  dd|  df       |j                         }|j                  d	d|  df       |j                         }|j                          |j                          ||z   |z   |z   }t	        |      S )
Nq T
dictionarya  
        SELECT
            cities.insee_code,
            cities.city_name as name,
            'city' as type,
            cities.insee_code as id,
            cities.longitude as lng,
            cities.latitude as lat,
            cities.postal_code,
            cities.department_code,
            departments.department_name,
            cities.region_code,
            regions.region_name,
            p.avg_price_per_sqm_apartment,
            p.avg_price_per_sqm_house,
            p.number_of_transactions,
            (SELECT COUNT(*) FROM districts WHERE districts.insee_code = cities.insee_code) as district_count
        FROM cities
        LEFT JOIN departments ON cities.department_code = departments.department_code
        LEFT JOIN regions ON cities.region_code = regions.region_code
        LEFT JOIN prices p ON cities.insee_code = p.insee_code AND p.data_year = 2024
        WHERE LOWER(CONVERT(cities.city_name USING utf8mb4)) LIKE LOWER(CONVERT(%s USING utf8mb4))
           OR cities.postal_code LIKE %s
        LIMIT 5
    %a/  
        SELECT
            region_name as name,
            'region' as type,
            region_code as id,
            longitude as lng,
            latitude as lat
        FROM regions
        WHERE LOWER(CONVERT(region_name USING utf8mb4)) LIKE LOWER(CONVERT(%s USING utf8mb4))
        LIMIT 5
    ai  
        SELECT
            department_name as name,
            'department' as type,
            department_code as id,
            longitude as lng,
            latitude as lat
        FROM departments
        WHERE LOWER(CONVERT(department_name USING utf8mb4)) LIKE LOWER(CONVERT(%s USING utf8mb4))
           OR department_code LIKE %s
        LIMIT 5
    aP  
        SELECT
            district_name as name,
            'district' as type,
            CONCAT(insee_code, '-', district_id) as id,
            longitude as lng,
            latitude as lat
        FROM districts
        WHERE LOWER(CONVERT(district_name USING utf8mb4)) LIKE LOWER(CONVERT(%s USING utf8mb4))
        LIMIT 5
    )
r   argsgetstripr   r   cursorexecutefetchallclose)query
connectionr*   citiesregionsdepartments	districtsresultss           r   searchr5     sU   LLS"%++-Er{"$J$/F NN 0 eWA,!E7!	%1'4 __F NN 
 eWA,
 ooG NN  eWA,!E7!	%' //#K NN 
 eWA,
 !I
LLN w,y8G7r   z/api/countriesc                      t               } | j                  d      }|j                  d       |j                         }|j	                          | j	                          t        |      S )NTr$   zw
        SELECT country_code as id, country_name as name, latitude as lat, longitude as lng
        FROM countries
    r   r*   r+   r,   r-   r   )connr*   	countriess      r   get_countriesr:   x  sV    D[[D[)F
NN  	 !I
LLNJJL9r   z/regionsc                      t               } | j                  d      }d}|j                  |       |j                         }|j	                          | j	                          t        |      S )NTr$   zmSELECT region_code as region_code, region_name as region_name, longitude as lng, latitude as lat FROM regionsr7   )r/   r*   r.   r1   s       r   get_regionsr<     sZ    "$J$/F{E
NN5ooG
LLN7r   z/departmentsc                     t         j                  j                  d      } t         j                  j                  d      }t               }|j	                  d      }| rd}|j                  || f       n#|rd}|j                  ||f       nt        g       S |j                         }|j                          |j                          t        |      S )Ndepartment_coderegion_codeTr$   z
            SELECT department_code, department_name, latitude as lat, longitude as lng
            FROM departments
            WHERE department_code = %s
        z
            SELECT department_code, department_name, latitude as lat, longitude as lng
            FROM departments
            WHERE region_code = %s
        	r   r'   r(   r   r*   r+   r   r,   r-   )r>   r?   r/   r*   r.   r2   s         r   get_departmentsrA     s    ll&&'89O,,""=1K"$J$/F
 	u01	
 	u{n-r{//#K
LLN;r   z/citiesc                  6   t         j                  j                  d      } t         j                  j                  d      }t               }|j	                  d      }| rd}|j                  || f       n#|rd}|j                  ||f       nt        g       S |j                         }|D ]E  }|j                  d      d |d<   |j                  d      d |d<   |j                  d	      Ad
|d	<   G |j                          |j                          t        |      S )N
insee_coder>   Tr$   a  
            SELECT
                cities.insee_code,
                cities.city_name as name,
                cities.latitude as lat,
                cities.longitude as lng,
                cities.department_code,
                departments.department_name,
                cities.region_code,
                regions.region_name,
                p.avg_price_per_sqm_apartment,
                p.avg_price_per_sqm_house,
                p.number_of_transactions,
                (SELECT COUNT(*) FROM districts WHERE districts.insee_code = cities.insee_code) as district_count
            FROM cities
            LEFT JOIN departments ON cities.department_code = departments.department_code
            LEFT JOIN regions ON cities.region_code = regions.region_code
            LEFT JOIN prices p ON cities.insee_code = p.insee_code AND p.data_year = 2024
            WHERE cities.insee_code = %s
        a  
            SELECT
                cities.insee_code,
                cities.city_name as name,
                cities.latitude as lat,
                cities.longitude as lng,
                cities.department_code,
                departments.department_name,
                cities.region_code,
                regions.region_name,
                p.avg_price_per_sqm_apartment,
                p.avg_price_per_sqm_house,
                p.number_of_transactions,
                (SELECT COUNT(*) FROM districts WHERE districts.insee_code = cities.insee_code) as district_count
            FROM cities
            LEFT JOIN departments ON cities.department_code = departments.department_code
            LEFT JOIN regions ON cities.region_code = regions.region_code
            LEFT JOIN prices p ON cities.insee_code = p.insee_code AND p.data_year = 2024
            WHERE cities.department_code = %s
        avg_price_per_sqm_apartmentavg_price_per_sqm_housenumber_of_transactionsr   r@   )rC   r>   r/   r*   r.   r0   citys          r   
get_citiesrH     s   !!,/Jll&&'89O"$J$/F( 	uzm,	( 	u01r{__F  /8812:26D./88-.6.2D*+88,-5-.D)*/ LLN6?r   z
/districtsc                  F   t         j                  j                  dd       } t               }|j	                  d      }| rd}|j                  || f       nd}|j                  |       |j                         }|j                          |j                          t        |      S )NrC   Tr$   z
            SELECT insee_code, district_name as name, longitude as lng, latitude as lat
            FROM districts
            WHERE insee_code = %s
        z|
            SELECT insee_code, district_name as name, longitude as lng, latitude as lat
            FROM districts
        )	r   r'   r(   r   r*   r+   r,   r-   r   )rC   r/   r*   r.   r3   s        r   get_districtsrJ     s    !!,5J"$J$/F
 	uzm, 	u!I
LLN9r   z/region/<region_code>c                      t        t              S r   r   )r?   s    r   show_regionrL          ",//r   z/department/<department_code>c                      t        t              S r   r   )r>   s    r   show_departmentrO     rM   r   z/city/<city_name>-<insee_code>c                      t        t              S r   r   )	city_namerC   s     r   	show_cityrR     rM   r   z/district/<district_id>c                      t        t              S r   r   )district_ids    r   show_districtrU     rM   r     c                     t        d      dfS )Nz404.htmlrV   )render_template)es    r   page_not_foundrZ   !  s    :&++r   c                     t               }|j                  d      }|j                  d| f       |j                         }|j	                          |j	                          |rt        di |S y )NTr$   z&SELECT * FROM users WHERE user_id = %sr   )r   r*   r+   fetchoner-   r   )user_idr/   r*   	user_datas       r   	load_userr_   %  se     #$J$/F
NN;gZH!I
LLN i  r   z/loginPOST)methodsc            
         t         j                  j                  d      } t         j                  j                  d      }t         j                  j                  d      dk(  }| r|st        ddd      dfS t	               }|j                  d	
      }|j                  d| f       |j                         }|j                          |j                          |rwt        j                  |d   |      r^t        d|d   |d   |d   |d   d|j                         D ci c]  \  }}|dvs|| c}}}t        ||       t        d	dd      S t        ddd      dfS c c}}w )Nemailpasswordremember_meonFz(Email et mot de passe sont obligatoires.successmessage  Tr$   z$SELECT * FROM users WHERE email = %spassword_hashr]   account_type)r]   rc   rk   rl   )rememberu   Connexion réussie !z Email ou mot de passe incorrect.i  r   )r   formr(   r   r   r*   r+   r\   r-   r   check_password_hashr   itemsr   )	rc   rd   re   r/   r*   r^   kvusers	            r   r   r   2  sX   LLW%E||
+H,,""=1T9K55_`acfff"$J$/F
NN9E8D!I
LLNV//	/0JHU 
i(G$#O4">2	

 !* 1t1Q>s5sq!tt
 	4+.44JKLL55WXY[^^^ us   E'Ez	/registerc            	      4   t         j                  j                  d      } t         j                  j                  d      }t         j                  j                  d      }t         j                  j                  d      }t         j                  j                  d      }t         j                  j                  d      }t         j                  j                  d      dk(  }| r
|r|r|r|r|st        d	d
d      dfS ||k7  rt        d	dd      dfS t	        j
                  |      j                  d      }t               }|j                         }		 |	j                  d| |||||f       |j                          t        ddd      |	j                          |j                          S # t        $ rF}
t        d	dt        |
       d      dfcY d }
~
|	j                          |j                          S d }
~
ww xY w# |	j                          |j                          w xY w)Nrc   rd   confirm_passwordrl   
first_name	last_namenewsletter_subscriptionrf   Fz"Tous les champs sont obligatoires.rg   rj   z'Les mots de passe ne correspondent pas.zutf-8z
            INSERT INTO users
            (email, password_hash, account_type, first_name, last_name, newsletter_subscription)
            VALUES (%s, %s, %s, %s, %s, %s)
        Tu   Inscription réussie !zErreur lors de l'inscription :   )r   rn   r(   r   r   generate_password_hashdecoder   r*   r+   commitr-   	Exceptionstr)rc   rd   ru   rl   rv   rw   rx   rk   r/   r*   rY   s              r   registerr   P  s    LLW%E||
+H||''(:;<<##N3L!!,/J  -I%ll../HITQ (8T^fo55YZ[]```##55^_`beee 11(;BB7KM #$J F  ]L*iI`a		c
 	44LMN 		  g57VWZ[\W]V^5_`acfff	g 	s0   5F# #	G2,G-G2G5 -G22G5 5"Hz/logoutc                  2    t                t        ddd      S )NTu   Déconnexion réussie.rg   )r   r   r   r   r   logoutr   v  s    Mt0HIJJr   z/api/accountGETc                      t        dt        j                  t        j                  t        j                  t        j
                  d      S )NT)	logged_inrc   rl   rv   rw   )r   r   rc   rl   rv   rw   r   r   r   api_accountr   {  s=     ##$11"--!++  r   )r   r   )r   r   z/api/favoritesc                     t        j                         } | j                  d      }| j                  d      }| j                  d      }t               }|j	                  d      }|j                  dt        j                  f       |j                         }|r|d   nd}|j                  d	t        j                  f       |j                         d
   }|s|dk\  rt        ddd      dfS |r|dk\  rt        ddd      dfS |j                  dt        j                  |||f       |j                          |j                          |j                          t        ddd      S )Nfavorite_typefavorite_codefavorite_nameTr$   zZ
        SELECT is_premium
        FROM user_subscriptions
        WHERE user_id = %s
    
is_premiumFzX
        SELECT COUNT(*) AS count
        FROM favorites
        WHERE user_id = %s
    count   zMLimite de 5 favoris atteinte. Passez en version premium pour en ajouter plus.rg   i  2   zLimite de 50 favoris atteinte.zz
        INSERT INTO favorites (user_id, favorite_type, favorite_code, favorite_name)
        VALUES (%s, %s, %s, %s)
    u   Favori ajouté avec succès !)r   get_jsonr(   r   r*   r+   r   idr\   r   r|   r-   )	datar   r   r   r/   r*   subscriptionr   favorite_counts	            r   add_favoriter     su    DHH_-MHH_-MHH_-M #$J$/F
NN  //		
 ??$L/;l+J NN  //		
 __&w/N .A-5  6E  F  G  IL  L  	L	",55UVWY\\\ NN  //=-	GI 
LLNt0OPQQr   c                      t               } | j                  d      }|j                  dt        j                  f       |j                         }|j                          | j                          t        d|d      S )NTr$   z@
        SELECT * FROM favorites
        WHERE user_id = %s
    )rh   	favorites)r   r*   r+   r   r   r,   r-   r   )r/   r*   r   s      r   get_favoritesr     so     #$J$/F
NN  //	 !I
LLNt)<==r   DELETEc                  d   t        j                         } | j                  d      }| j                  d      }t               }|j	                         }|j                  dt        j                  ||f       |j                          |j                          |j                          t        ddd      S )Nr   r   zl
        DELETE FROM favorites
        WHERE user_id = %s AND favorite_type = %s AND favorite_code = %s
    Tu   Favori supprimé avec succès !rg   )r   r   r(   r   r*   r+   r   r   r|   r-   r   )r   r   r   r/   r*   s        r   delete_favoriter     s     DHH_-MHH_-M"$J F
NN  //=-	8: 
LLNt0QRSSr   z/api/favorites/checkc                  z   t         j                  j                  d      } t         j                  j                  d      }t               }|j	                  d      }|j                  dt        j                  | |f       |j                         d u}|j                          |j                          t        d|i      S )NtypecodeTr$   zn
        SELECT 1 FROM favorites
        WHERE user_id = %s AND favorite_type = %s AND favorite_code = %s
    is_favorite)r   r'   r(   r   r*   r+   r   r   r\   r-   r   )r   r   r/   r*   r   s        r   check_favoriter     s     LL$$V,MLL$$V,M"$J$/F
NN  //=-	8: //#4/K
LLNM;/00r   z/api/similar_citiesc            	         t         j                  j                  d      } | st        g       S d }	 t	               }|j                  dd      }|j                  d| f       |j                         }|r
|d   |d   At        g       |r|j                          |r"|j                         r|j                          S S S |d   |d   f}|j                  d| f       |j                         }g }|D ]k  }|d   |d   f}t        ||      j                  }	|	dk  s)|d	   xs |d
   }
|j                  |d   |
t        |
      nd t        |	d      |d   |d   d       m |j!                  d        t        |d d       |r|j                          |r"|j                         r|j                          S S S # t"        $ rY}t%        d|        t        g       cY d }~r|j                          |r"|j                         r|j                          S S S d }~ww xY w# r|j                          |r"|j                         r|j                          w w w xY w)NrC   Tr%   buffereda/  
            SELECT c.city_name, c.latitude as lat, c.longitude as lng,
                   p.avg_price_per_sqm_apartment, p.avg_price_per_sqm_house
            FROM cities c
            LEFT JOIN prices p ON c.insee_code = p.insee_code AND p.data_year = 2024
            WHERE c.insee_code = %s
        latlnga  
            SELECT c.city_name, c.latitude as lat, c.longitude as lng,
                   p.avg_price_per_sqm_apartment, p.avg_price_per_sqm_house
            FROM cities c
            LEFT JOIN prices p ON c.insee_code = p.insee_code AND p.data_year = 2024
            WHERE c.insee_code != %s
              AND c.latitude IS NOT NULL
              AND c.longitude IS NOT NULL
        
   rD   rE   rQ      )namepricedistancer   r   c                     | d   S )Nr   r   )xs    r   <lambda>z$get_similar_cities.<locals>.<lambda>  s
    !J- r   )keyr   z([DEBUG] Erreur dans get_similar_cities: )r   r'   r(   r   r   r*   r+   r\   r-   is_connectedr,   r   
kilometersappendfloatroundsortr}   print)rC   r/   r*   current_citycurrent_coords
all_citiessimilar_citiesrG   city_coordsr   r   rY   s               r   get_similar_citiesr     sl   !!,/Jr{J1&(
""dT"B  ]	 (|E2:l5>Q>Y2;B LLN*113 4:E 'u-|E/BC  ]	 __&
 	D;U4K<GGH"}:;^tD]?^%% --2->U5\D %h 2;;' 	 	 78~bq)*
 LLN*113 4:  8<=r{LLN*113 4: LLN*113 4:s>   AF3 =AF3 A%F3 3	H<HHH HH 8Iz/api/prices/<insee_code>c                    	 t               }|j                  dd      }|j                  d| f       |j                         }g }|D ]`  }t	        |d         }t        |dd      }|d   t        |d         nt        |d         }|j                  |j                         |d       b t        |g d	      |j                          |j                          S # t        $ rB}	t        d
t        |	      i      dfcY d }	~	j                          j                          S d }	~	ww xY w# j                          j                          w xY w)NTr   z
            SELECT
                data_year AS year,
                avg_price_per_sqm_apartment,
                avg_price_per_sqm_house
            FROM prices
            WHERE insee_code = %s
            ORDER BY data_year
        yearr   rD   rE   )dater   )
pastPricesfuturePriceserrorry   )r   r*   r+   r,   intr   r   r   	isoformatr   r-   r}   r~   )
rC   r/   r*   r4   past_pricesrowr   date_objr   rY   s
             r   
get_pricesr   "  sL   &(
""dT"B  ]	 //# 	OCs6{#DD!Q'HADEbAcAoE#;<=uz{~  @Y  |Z  v[E(:(:(<uMN		O k2FG 		  /Q()3..	/ 	s0   B4C 	D" D7D"8D% D""D% %"Ez/api/city-datac                     t         j                  j                  d      } | st        ddi      dfS t        j                  |       }|st        ddi      dfS d|vrg |d<   	 |d   |d   |d	   |d
   |d   |d   |d   t        |d         d|d   d}t        |      S # t        $ r'}t        d|        t        ddi      dfcY d }~S d }~ww xY w)NrC   r   u$   Le paramètre insee_code est requis.rj   u%   Ville non trouvée ou erreur serveur.rV   r3   r   latitude	longituderD   rE   rF   )r   rC   r   r   rD   rE   rF   district_count)rG   r3   u7   [DEBUG] Erreur lors de la préparation de la réponse: u.   Erreur lors de la préparation de la réponse.ry   )	r   r'   r(   r   CityDataManagerget_city_datalenr}   r   )rC   	city_dataresponserY   s       r   r   r   @  s   !!,/J!GHI3NN--j9I!HIJCOO)#!#	+Y "&)'5%j1&{3/89V/W+45N+O*34L*M"%i&<"=	 #;/
 x   YGsKL!QRSUXXXYs   !<B 	C'C	C	Cz/api/real-estate-sitesc                  <   	 t               } | j                  d      }d}|j                  |       |j                         }|j	                          | j	                          t        d|d      S # t        $ r#}t        dt        |      d      dfcY d }~S d }~ww xY w)NTr$   z
        SELECT website_id, name, url, logo_url, description, allow_iframe
        FROM real_estate_websites
        WHERE is_active = 1
        ORDER BY name
        )rh   sitesFrg   ry   )r   r*   r+   r,   r-   r   r}   r~   )r/   r*   r.   r   rY   s        r   get_real_estate_sitesr   _  s    C&(
""d"3 	u!4%899 C5SV<=sBBCs   A,A/ /	B8BBBz/api/schoolsc                  0   t               } | j                  dd      }t        j                  j	                  d      }t        j                  j	                  dt
              }t        j                  j	                  dt
              }t        j                  j	                  ddt
        	      }|r|j                  d
|f       n*|r|r|j                  d||||f       nt        ddi      dfS |j                         }|j                          t        |      S )NTr   rC   r   )r   lonradiusg      ?)defaultr   z
            SELECT service_name, address, missions, phone, website, latitude, longitude
            FROM public_services
            WHERE insee_code = %s AND category = 'school'
            LIMIT 20
        a  
            SELECT service_name, address, missions, phone, website, latitude, longitude,
                   (6371 * ACOS(
                       COS(RADIANS(%s)) * COS(RADIANS(latitude)) *
                       COS(RADIANS(longitude) - RADIANS(%s)) +
                       SIN(RADIANS(%s)) * SIN(RADIANS(latitude))
                   )) AS distance
            FROM public_services
            WHERE category = 'school'
            HAVING distance < %s
            ORDER BY distance
            LIMIT 20
        r   u   Paramètres manquantsrj   )
r   r*   r   r'   r(   r   r+   r   r,   r-   )r/   r*   rC   r   r   r   schoolss          r   get_schoolsr   t  s    "$J$>F!!,/J
,,

5u

-C
,,

5u

-C\\h%@F  
 ]	 
  3V$	& !89:C??ooG
LLN7r   N)9flask_loginr   r   r   r   r   r   flaskr	   r
   r   r   r   r   r   classesr   r   r   r   r   geopy.distancer   __name__bplogin_manager
login_viewr   router    r5   r:   r<   rA   rH   rJ   rL   rO   rR   rU   errorhandlerrZ   user_loaderr_   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s   f f _ _ _ M M C C #x"R " KZ #0 0 )U Ut 

 
 *  .   > )B BH , . 
!"0 #0 
)*0 +0 
*+0 ,0 
#$0 %0 , , 
 
 (VH%_ &_: +x(# )#J )fX&K 'K .5'*  + # 4
VH-(R  .(RT 
UG,>  -> 
XJ/T  0T" 
 5'21  31  
 6 !6p 
$% &: 
UG,Y -Y< 
"UG4C 5C$ #.$ $r   