#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import os
import sys
import urllib.parse
import email

# ==========================================
# CONFIGURATION DE LA BASE DE DONNÉES MYSQL
# ==========================================
# Modifiez ces valeurs pour correspondre à votre configuration cPanel
MYSQL_HOST = "localhost"
MYSQL_DB = "www2gglulaval_gite_correction"
MYSQL_USER = "www2gglulaval_gite"
MYSQL_PASSWORD = "Uv7.pFfYxOmrSFXQ"
MYSQL_CHARSET = "utf8"

# Nom du fichier de base de données local (pour le développement)
SQLITE_DB_NAME = "gite.db"

def sqlite_concat(*args):
    """
    Simule la fonction MySQL CONCAT dans SQLite en concaténant tous les arguments non-nuls.
    """
    return ''.join(str(arg) for arg in args if arg is not None)

def connect_database():
    """
    Établit la connexion à la base de données.
    Tente d'abord de charger SQLite si gite.db est présent,
    sinon se connecte à MySQL.
    
    Retourne:
        connection, cursor, is_sqlite (boolean)
    """
    script_dir = os.path.dirname(os.path.abspath(__file__))
    sqlite_path = os.path.join(script_dir, SQLITE_DB_NAME)
    
    if not os.path.exists(sqlite_path):
        sqlite_path = os.path.join(os.path.dirname(script_dir), SQLITE_DB_NAME)
        
    if os.path.exists(sqlite_path):
        try:
            import sqlite3
            connection = sqlite3.connect(sqlite_path)
            connection.create_function("CONCAT", -1, sqlite_concat)
            cursor = connection.cursor()
            return connection, cursor, True
        except Exception:
            pass

    # Connexion à MySQL (production cPanel)
    try:
        import MySQLdb
        connection = MySQLdb.connect(
            host=MYSQL_HOST, 
            db=MYSQL_DB,
            user=MYSQL_USER,
            passwd=MYSQL_PASSWORD,
            charset=MYSQL_CHARSET
        )
        cursor = connection.cursor()
        cursor.execute("SET NAMES 'utf8'")
        return connection, cursor, False
    except ImportError:
        try:
            import pymysql
            connection = pymysql.connect(
                host=MYSQL_HOST,
                db=MYSQL_DB,
                user=MYSQL_USER,
                password=MYSQL_PASSWORD,
                charset=MYSQL_CHARSET
            )
            cursor = connection.cursor()
            cursor.execute("SET NAMES 'utf8'")
            return connection, cursor, False
        except ImportError:
            print("Content-type: text/html; charset=UTF-8\n")
            print("<html><head><title>Erreur de Base de Données</title></head><body>")
            print("<h2>Erreur Critique de Connexion</h2>")
            print("<p>Impossible de charger les adaptateurs de base de données.</p>")
            print(f"<p>Assurez-vous que le module Python <b>mysqlclient</b> (MySQLdb) ou <b>pymysql</b> est installé sur votre serveur cPanel.</p>")
            print(f"<p>En local, vous pouvez aussi simplement placer le fichier <code>{SQLITE_DB_NAME}</code> dans le dossier de l'application.</p>")
            print("</body></html>")
            sys.exit(1)
    except Exception as error:
        print("Content-type: text/html; charset=UTF-8\n")
        print("<html><head><title>Erreur de Base de Données</title></head><body>")
        print("<h2>Erreur lors de la connexion à la base de données</h2>")
        print(f"<p>Détails de l'erreur : <code>{error}</code></p>")
        print("<p>Veuillez vérifier les informations de connexion MySQL dans le fichier <code>db_adapter.py</code>.</p>")
        print("</body></html>")
        sys.exit(1)

def setup_temporary_table(cursor, is_sqlite, req_tmp):
    """
    Crée la table temporaire 'tmp' de façon compatible entre MySQL et SQLite.
    """
    if is_sqlite:
        cursor.execute("DROP TABLE IF EXISTS tmp")
        cursor.execute("CREATE TEMPORARY TABLE tmp (giteId INTEGER)")
    else:
        cursor.execute("DROP TEMPORARY TABLE IF EXISTS tmp")
        cursor.execute("CREATE TEMPORARY TABLE tmp (giteId INT(10)) ENGINE = MEMORY")
        
    cursor.execute(req_tmp)

def get_css_style():
    """
    Tente de charger style.css du dossier pour l'intégrer en ligne dans l'en-tête HTML,
    ce qui évite les liens brisés de ressources statiques sur cPanel.
    """
    script_dir = os.path.dirname(os.path.abspath(__file__))
    css_path = os.path.join(script_dir, "style.css")
    
    if not os.path.exists(css_path):
        css_path = os.path.join(os.path.dirname(script_dir), "style.css")
        
    if os.path.exists(css_path):
        try:
            with open(css_path, 'r', encoding='utf-8') as f:
                return f"<style>\n{f.read()}\n</style>"
        except Exception:
            pass
            
    return '<link rel="stylesheet" href="/style.css">'

# ==========================================
# CLASSE DE COMPATIBILITÉ POUR PYTHON 3.13+
# ==========================================
class FieldStorageFallback:
    """
    Une implémentation minimale et compatible pour remplacer cgi.FieldStorage
    qui a été supprimée dans Python 3.13+. Gère le URL-encoded et le multipart (upload).
    """
    def __init__(self):
        self.fields = {}
        
        # 1. Analyse des paramètres de l'URL (GET)
        query_string = os.environ.get("QUERY_STRING", "")
        if query_string:
            for k, v in urllib.parse.parse_qsl(query_string, keep_blank_values=True):
                if k not in self.fields:
                    self.fields[k] = []
                self.fields[k].append(v)
                
        # 2. Analyse des paramètres du corps de la requête (POST)
        request_method = os.environ.get("REQUEST_METHOD", "").upper()
        if request_method == "POST":
            try:
                content_length = int(os.environ.get("CONTENT_LENGTH", 0))
            except ValueError:
                content_length = 0
                
            if content_length > 0:
                body_bytes = sys.stdin.buffer.read(content_length)
                content_type = os.environ.get("CONTENT_TYPE", "")
                
                # Cas 1 : Multipart (file upload)
                if "multipart/form-data" in content_type and "boundary=" in content_type:
                    boundary = content_type.split("boundary=")[1].strip()
                    if boundary.startswith('"') and boundary.endswith('"'):
                        boundary = boundary[1:-1]
                        
                    # Construction d'un message MIME pour utiliser le module standard email
                    headers = f"Content-Type: multipart/form-data; boundary={boundary}\n\n"
                    msg = email.message_from_bytes(headers.encode('utf-8') + body_bytes)
                    
                    for part in msg.walk():
                        if part.is_multipart():
                            continue
                            
                        disposition = part.get("Content-Disposition", "")
                        if not disposition:
                            continue
                            
                        params = {}
                        for item in disposition.split(';'):
                            item = item.strip()
                            if '=' in item:
                                k, v = item.split('=', 1)
                                params[k.lower()] = v.strip('"')
                                
                        name = params.get("name")
                        if not name:
                            continue
                            
                        filename = params.get("filename")
                        if filename is not None:
                            # C'est un téléversement de fichier
                            file_data = part.get_payload(decode=True)
                            mimetype = part.get_content_type()
                            
                            # Crée une fausse structure FieldStorage pour compatibilité
                            class FileUpload:
                                def __init__(self, filename, mimetype, value):
                                    self.filename = filename
                                    self.type = mimetype
                                    self.value = value
                                    self.file = None
                            
                            if name not in self.fields:
                                self.fields[name] = []
                            self.fields[name].append(FileUpload(filename, mimetype, file_data))
                        else:
                            # C'est un champ de texte standard
                            val = part.get_payload(decode=True).decode('utf-8', errors='replace')
                            if name not in self.fields:
                                self.fields[name] = []
                            self.fields[name].append(val)
                
                # Cas 2 : URL Encoded standard
                else:
                    body_str = body_bytes.decode('utf-8', errors='replace')
                    for k, v in urllib.parse.parse_qsl(body_str, keep_blank_values=True):
                        if k not in self.fields:
                            self.fields[k] = []
                        self.fields[k].append(v)

    def keys(self):
        return self.fields.keys()

    def __iter__(self):
        return iter(self.fields)

    def getvalue(self, key, default=None):
        if key in self.fields:
            values = self.fields[key]
            # Si le champ contient des fichiers téléversés, on retourne l'objet ou la liste d'objets
            # Sinon si c'est une liste à un seul élément, on renvoie la valeur brute
            if len(values) == 1:
                return values[0]
            return values
        return default

    def getfirst(self, key, default=None):
        if key in self.fields and self.fields[key]:
            val = self.fields[key][0]
            # Si c'est un objet FileUpload, retourne son contenu brut pour compatibilité
            if hasattr(val, 'filename'):
                return val.value
            return val
        return default

def get_form_data():
    """
    Retourne les données soumises par le formulaire.
    Tente d'utiliser le module standard 'cgi' s'il est présent,
    sinon utilise le fallback personnalisé pour Python 3.13+.
    """
    try:
        import cgi
        # On essaie d'utiliser cgi, mais sur Python 3.13+ cela lèvera un ImportError
        return cgi.FieldStorage()
    except ImportError:
        # Fallback pour Python 3.13+
        return FieldStorageFallback()
