from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask import Blueprint, render_template_string, request, jsonify, flash, redirect, url_for
from flask_login import login_user, logout_user, login_required, current_user
from classes import User, City, District, get_db_connection, bcrypt
from geopy.distance import geodesic

bp = Blueprint('routes', __name__)

login_manager = LoginManager(bp)
login_manager.login_view = 'login'
    
html_content = """
<!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>"""

@bp.route("/")
def home():
    return render_template_string(html_content)
    
@bp.route('/search')
def search():
    query = request.args.get('q', '').strip()
    if not query:
        return jsonify([])

    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)

    # Recherche dans les villes (insensible à la casse et aux accents)
    cursor.execute("""
        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
    """, (f'%{query}%', f'%{query}%'))

    cities = cursor.fetchall()

    # Recherche dans les régions
    cursor.execute("""
        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
    """, (f'%{query}%',))
    regions = cursor.fetchall()

    # Recherche dans les départements
    cursor.execute("""
        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
    """, (f'%{query}%', f'%{query}%'))
    departments = cursor.fetchall()

    # Recherche dans les quartiers
    cursor.execute("""
        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
    """, (f'%{query}%',))
    districts = cursor.fetchall()

    cursor.close()
    connection.close()

    # Fusionne les résultats
    results = cities + regions + departments + districts
    return jsonify(results)




@bp.route('/api/countries')
def get_countries():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute("""
        SELECT country_code as id, country_name as name, latitude as lat, longitude as lng
        FROM countries
    """)
    countries = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(countries)

@bp.route('/regions')
def get_regions():
    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)
    query = "SELECT region_code as region_code, region_name as region_name, longitude as lng, latitude as lat FROM regions"
    cursor.execute(query)
    regions = cursor.fetchall()
    cursor.close()
    connection.close()
    return jsonify(regions)

@bp.route('/departments')
def get_departments():
    department_code = request.args.get('department_code')
    region_code = request.args.get('region_code')

    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)

    if department_code:
        query = """
            SELECT department_code, department_name, latitude as lat, longitude as lng
            FROM departments
            WHERE department_code = %s
        """
        cursor.execute(query, (department_code,))
    elif region_code:
        query = """
            SELECT department_code, department_name, latitude as lat, longitude as lng
            FROM departments
            WHERE region_code = %s
        """
        cursor.execute(query, (region_code,))
    else:
        return jsonify([])

    departments = cursor.fetchall()
    cursor.close()
    connection.close()
    return jsonify(departments)



@bp.route('/cities')
def get_cities():
    insee_code = request.args.get('insee_code')
    department_code = request.args.get('department_code')
    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)

    if insee_code:
        query = """
            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
        """
        cursor.execute(query, (insee_code,))
    elif department_code:
        query = """
            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
        """
        cursor.execute(query, (department_code,))
    else:
        return jsonify([])

    cities = cursor.fetchall()

    # Initialiser les champs de prix à None si absents
    for city in cities:
        if city.get("avg_price_per_sqm_apartment") is None:
            city["avg_price_per_sqm_apartment"] = None
        if city.get("avg_price_per_sqm_house") is None:
            city["avg_price_per_sqm_house"] = None
        if city.get("number_of_transactions") is None:
            city["number_of_transactions"] = 0

    cursor.close()
    connection.close()
    return jsonify(cities)

@bp.route('/districts')
def get_districts():
    insee_code = request.args.get('insee_code', None)
    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)
    if insee_code:
        query = """
            SELECT insee_code, district_name as name, longitude as lng, latitude as lat
            FROM districts
            WHERE insee_code = %s
        """
        cursor.execute(query, (insee_code,))
    else:
        query = """
            SELECT insee_code, district_name as name, longitude as lng, latitude as lat
            FROM districts
        """
        cursor.execute(query)
    districts = cursor.fetchall()
    cursor.close()
    connection.close()
    return jsonify(districts)


@bp.route('/region/<region_code>')
def show_region(region_code):
    # Redirige vers la carte centrée sur la région
    return render_template_string(html_content)

@bp.route('/department/<department_code>')
def show_department(department_code):
    # Redirige vers la carte centrée sur le département
    return render_template_string(html_content)

@bp.route('/city/<city_name>-<insee_code>')
def show_city(city_name, insee_code):
    # Redirige vers la carte centrée sur la ville
    return render_template_string(html_content)

@bp.route('/district/<district_id>')
def show_district(district_id):
    # Redirige vers la carte centrée sur le quartier
    return render_template_string(html_content)

@bp.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@login_manager.user_loader
def load_user(user_id):
    # Logique pour charger l'utilisateur depuis la base de données
    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)
    cursor.execute("SELECT * FROM users WHERE user_id = %s", (user_id,))
    user_data = cursor.fetchone()
    cursor.close()
    connection.close()
    if user_data:
        return User(**user_data)
    return None

@bp.route('/login', methods=['POST'])
def login():
    email = request.form.get('email')
    password = request.form.get('password')
    remember_me = request.form.get('remember_me') == 'on'

    if not email or not password:
        return jsonify({"success": False, "message": "Email et mot de passe sont obligatoires."}), 400

    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)
    cursor.execute("SELECT * FROM users WHERE email = %s", (email,))
    user_data = cursor.fetchone()
    cursor.close()
    connection.close()

    if user_data and bcrypt.check_password_hash(user_data['password_hash'], password):
        # Crée l'objet User avec tous les champs retournés par la base de données
        user = User(
            user_id=user_data['user_id'],
            email=user_data['email'],
            password_hash=user_data['password_hash'],
            account_type=user_data['account_type'],
            **{k: v for k, v in user_data.items() if k not in ['user_id', 'email', 'password_hash', 'account_type']}
        )
        login_user(user, remember=remember_me)
        return jsonify({"success": True, "message": "Connexion réussie !"})
    else:
        return jsonify({"success": False, "message": "Email ou mot de passe incorrect."}), 401
        
@bp.route('/register', methods=['POST'])
def register():
    # Récupérer les données du formulaire
    email = request.form.get('email')
    password = request.form.get('password')
    confirm_password = request.form.get('confirm_password')
    account_type = request.form.get('account_type')
    first_name = request.form.get('first_name')
    last_name = request.form.get('last_name')
    newsletter_subscription = request.form.get('newsletter_subscription') == 'on'

    # Valider les données
    if not email or not password or not confirm_password or not account_type or not first_name or not last_name:
        return jsonify({"success": False, "message": "Tous les champs sont obligatoires."}), 400

    if password != confirm_password:
        return jsonify({"success": False, "message": "Les mots de passe ne correspondent pas."}), 400

    # Hacher le mot de passe
    password_hash = bcrypt.generate_password_hash(password).decode('utf-8')

    # Enregistrer l'utilisateur
    connection = get_db_connection()
    cursor = connection.cursor()
    try:
        cursor.execute("""
            INSERT INTO users
            (email, password_hash, account_type, first_name, last_name, newsletter_subscription)
            VALUES (%s, %s, %s, %s, %s, %s)
        """, (email, password_hash, account_type, first_name, last_name, newsletter_subscription))
        connection.commit()
        return jsonify({"success": True, "message": "Inscription réussie !"})
    except Exception as e:
        return jsonify({"success": False, "message": f"Erreur lors de l'inscription : {str(e)}"}), 500
    finally:
        cursor.close()
        connection.close()

@bp.route('/logout', methods=['POST'])
def logout():
    logout_user()
    return jsonify({"success": True, "message": "Déconnexion réussie."})

@bp.route('/api/account', methods=['GET'])
@login_required
def api_account():
    return jsonify({
        "logged_in": True,
        "email": current_user.email,
        "account_type": current_user.account_type,
        "first_name": current_user.first_name,
        "last_name": current_user.last_name
    })

from flask import jsonify, request
from flask_login import current_user, login_required

@bp.route('/api/favorites', methods=['POST'])
@login_required
def add_favorite():
    data = request.get_json()
    favorite_type = data.get('favorite_type')  # 'region', 'department', 'city', ou 'district'
    favorite_code = data.get('favorite_code')
    favorite_name = data.get('favorite_name')

    # Vérifie si l'utilisateur est premium
    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)
    cursor.execute("""
        SELECT is_premium
        FROM user_subscriptions
        WHERE user_id = %s
    """, (current_user.id,))
    subscription = cursor.fetchone()
    is_premium = subscription['is_premium'] if subscription else False

    # Compte le nombre de favoris existants
    cursor.execute("""
        SELECT COUNT(*) AS count
        FROM favorites
        WHERE user_id = %s
    """, (current_user.id,))
    favorite_count = cursor.fetchone()['count']

    # Vérifie la limite
    if not is_premium and favorite_count >= 5:
        return jsonify({"success": False, "message": "Limite de 5 favoris atteinte. Passez en version premium pour en ajouter plus."}), 403
    elif is_premium and favorite_count >= 50:
        return jsonify({"success": False, "message": "Limite de 50 favoris atteinte."}), 403

    # Ajoute le favori
    cursor.execute("""
        INSERT INTO favorites (user_id, favorite_type, favorite_code, favorite_name)
        VALUES (%s, %s, %s, %s)
    """, (current_user.id, favorite_type, favorite_code, favorite_name))
    connection.commit()
    cursor.close()
    connection.close()

    return jsonify({"success": True, "message": "Favori ajouté avec succès !"})

@bp.route('/api/favorites', methods=['GET'])
@login_required
def get_favorites():
    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)
    cursor.execute("""
        SELECT * FROM favorites
        WHERE user_id = %s
    """, (current_user.id,))
    favorites = cursor.fetchall()
    cursor.close()
    connection.close()

    return jsonify({"success": True, "favorites": favorites})

@bp.route('/api/favorites', methods=['DELETE'])
@login_required
def delete_favorite():
    data = request.get_json()
    favorite_type = data.get('favorite_type')
    favorite_code = data.get('favorite_code')

    connection = get_db_connection()
    cursor = connection.cursor()
    cursor.execute("""
        DELETE FROM favorites
        WHERE user_id = %s AND favorite_type = %s AND favorite_code = %s
    """, (current_user.id, favorite_type, favorite_code))
    connection.commit()
    cursor.close()
    connection.close()

    return jsonify({"success": True, "message": "Favori supprimé avec succès !"})

@bp.route('/api/favorites/check', methods=['GET'])
@login_required
def check_favorite():
    favorite_type = request.args.get('type')
    favorite_code = request.args.get('code')

    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True)
    cursor.execute("""
        SELECT 1 FROM favorites
        WHERE user_id = %s AND favorite_type = %s AND favorite_code = %s
    """, (current_user.id, favorite_type, favorite_code))
    is_favorite = cursor.fetchone() is not None
    cursor.close()
    connection.close()

    return jsonify({"is_favorite": is_favorite})
    
@bp.route('/api/similar_cities')
def get_similar_cities():
    insee_code = request.args.get('insee_code')
    if not insee_code:
        return jsonify([])
    connection = None
    try:
        connection = get_db_connection()
        cursor = connection.cursor(dictionary=True, buffered=True)
        # 1. Récupère les coordonnées de la ville actuelle + ses prix
        cursor.execute("""
            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
        """, (insee_code,))
        current_city = cursor.fetchone()
        if not current_city or current_city['lat'] is None or current_city['lng'] is None:
            return jsonify([])
        current_coords = (current_city['lat'], current_city['lng'])
        # 2. Récupère les villes à moins de 10 km (filtre côté SQL)
        cursor.execute("""
            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
        """, (insee_code,))
        all_cities = cursor.fetchall()
        similar_cities = []
        for city in all_cities:
            city_coords = (city['lat'], city['lng'])
            distance = geodesic(current_coords, city_coords).kilometers
            if distance < 10:
                price = city['avg_price_per_sqm_apartment'] or city['avg_price_per_sqm_house']
                similar_cities.append({
                    'name': city['city_name'],
                    'price': float(price) if price is not None else None,
                    'distance': round(distance, 1),
                    'lat': city['lat'],
                    'lng': city['lng'],
                })
        # 3. Trie par distance et retourne les 5 plus proches
        similar_cities.sort(key=lambda x: x['distance'])
        return jsonify(similar_cities[:5])
    except Exception as e:
        print(f"[DEBUG] Erreur dans get_similar_cities: {e}")
        return jsonify([])
    finally:
        if cursor:
            cursor.close()
        if connection and connection.is_connected():
            connection.close()

@bp.route('/api/prices/<insee_code>')
def get_prices(insee_code):
    try:
        connection = get_db_connection()
        cursor = connection.cursor(dictionary=True, buffered=True)
        cursor.execute("""
            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
        """, (insee_code,))
        results = cursor.fetchall()

        past_prices = []
        for row in results:
            year = int(row['year'])  # data_year est déjà un int, pas besoin de YEAR()
            date_obj = date(year, 1, 1)  # Crée une date au 1er janvier de l'année
            price = float(row['avg_price_per_sqm_apartment']) if row['avg_price_per_sqm_apartment'] is not None else float(row['avg_price_per_sqm_house'])
            past_prices.append({"date": date_obj.isoformat(), "price": price})

        return jsonify({"pastPrices": past_prices, "futurePrices": []})
    except Exception as e:
        return jsonify({"error": str(e)}), 500
    finally:
        cursor.close()
        connection.close()
    
@bp.route('/api/city-data', methods=['GET'])
def city_data():
    insee_code = request.args.get('insee_code')
    if not insee_code:
        return jsonify({"error": "Le paramètre insee_code est requis."}), 400
    city_data = CityDataManager.get_city_data(insee_code)
    if not city_data:
        return jsonify({"error": "Ville non trouvée ou erreur serveur."}), 404
    if 'districts' not in city_data:
        city_data['districts'] = []
    try:
        response = {
            "city": {
                "name": city_data["name"],
                "insee_code": city_data["insee_code"],
                "latitude": city_data["latitude"],
                "longitude": city_data["longitude"],
                "avg_price_per_sqm_apartment": city_data["avg_price_per_sqm_apartment"],
                "avg_price_per_sqm_house": city_data["avg_price_per_sqm_house"],
                "number_of_transactions": city_data["number_of_transactions"],
                "district_count": len(city_data["districts"]),
            },
            "districts": city_data["districts"]
        }
        return jsonify(response)
    except Exception as e:
        print(f"[DEBUG] Erreur lors de la préparation de la réponse: {e}")
        return jsonify({"error": "Erreur lors de la préparation de la réponse."}), 500

   

@bp.route('/api/real-estate-sites', methods=['GET'])
def get_real_estate_sites():
    try:
        connection = get_db_connection()
        cursor = connection.cursor(dictionary=True)
        query = """
        SELECT website_id, name, url, logo_url, description, allow_iframe
        FROM real_estate_websites
        WHERE is_active = 1
        ORDER BY name
        """
        cursor.execute(query)
        sites = cursor.fetchall()
        cursor.close()
        connection.close()
        return jsonify({"success": True, "sites": sites})
    except Exception as e:
        return jsonify({"success": False, "message": str(e)}), 500
        
from flask import jsonify, request

@bp.route('/api/schools')
def get_schools():     
    connection = get_db_connection()
    cursor = connection.cursor(dictionary=True, buffered=True)
    insee_code = request.args.get('insee_code')
    lat = request.args.get('lat', type=float)
    lon = request.args.get('lon', type=float)
    radius = request.args.get('radius', default=1.0, type=float)  # Rayon en km



    if insee_code:  # Filtre par code INSEE (ville)
        cursor.execute("""
            SELECT service_name, address, missions, phone, website, latitude, longitude
            FROM public_services
            WHERE insee_code = %s AND category = 'school'
            LIMIT 20
        """, (insee_code,))
    elif lat and lon:  # Filtre par proximité (quartier)
        cursor.execute("""
            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
        """, (lat, lon, lat, radius))
    else:
        return jsonify({"error": "Paramètres manquants"}), 400

    schools = cursor.fetchall()
    cursor.close()
    return jsonify(schools)