#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Extraction des food trucks (NAF 2025 - 5612Y) depuis la base Sirene
====================================================================
VERSION CSV LOCAL : utilise un fichier StockEtablissement_utf8.csv
déjà téléchargé localement (pas de re-téléchargement).

Étude démographie food truck France 2026 - wikifoodtruck.fr
Auteur : François Van Den Bossche

Source : Base Sirene (Insee, Licence Ouverte 2.0)
https://www.data.gouv.fr/datasets/base-sirene-des-entreprises-et-de-leurs-etablissements-siren-siret/

Durée attendue : 5 à 15 minutes selon la puissance du PC.
"""

import os
import sys
import time
from pathlib import Path

# ============================================================================
# CONFIGURATION
# ============================================================================

# Le fichier doit être dans le MÊME dossier que ce script
FICHIER_CSV_SOURCE = "StockEtablissement_utf8.csv"
FICHIER_CSV_TEMP = "_food_trucks_temp.csv"
FICHIER_CSV_SORTIE = "food_trucks_5612y_france.csv"


# ============================================================================
# UTILITAIRES
# ============================================================================

def banniere(texte):
    print()
    print("=" * 72)
    print(f"  {texte}")
    print("=" * 72)


def verifier_duckdb():
    """Vérifie que DuckDB est installé."""
    try:
        import duckdb
        print(f"  [OK] DuckDB version {duckdb.__version__} disponible")
        return True
    except ImportError:
        print("  [ERREUR] DuckDB n'est pas installé.")
        print("  Installation : python -m pip install duckdb")
        return False


def verifier_fichier_source():
    """Vérifie que le CSV source est présent dans le dossier."""
    chemin = Path(FICHIER_CSV_SOURCE)
    if not chemin.exists():
        print(f"  [ERREUR] Le fichier '{FICHIER_CSV_SOURCE}' est introuvable")
        print(f"  dans le dossier courant : {Path.cwd()}")
        print()
        print(f"  Fichiers présents dans ce dossier :")
        for f in Path.cwd().iterdir():
            if f.is_file():
                taille = f.stat().st_size
                if taille > 1e9:
                    taille_str = f"{taille / 1e9:.2f} Go"
                elif taille > 1e6:
                    taille_str = f"{taille / 1e6:.2f} Mo"
                else:
                    taille_str = f"{taille / 1e3:.1f} Ko"
                print(f"      {f.name} ({taille_str})")
        return False
    
    taille_go = chemin.stat().st_size / 1e9
    print(f"  [OK] Fichier source trouvé : {FICHIER_CSV_SOURCE} ({taille_go:.2f} Go)")
    
    # Sanity check : le fichier doit faire plusieurs Go
    if taille_go < 5:
        print(f"  [ATTENTION] Le fichier semble petit ({taille_go:.2f} Go).")
        print(f"  Le fichier StockEtablissement complet devrait faire ~9 Go.")
        print(f"  S'il est tronqué ou corrompu, l'extraction sera incomplète.")
        reponse = input("  Continuer quand même ? (o/N) : ").strip().lower()
        if reponse != 'o':
            return False
    
    return True


def detecter_colonne_naf25():
    """Détecte la colonne NAF 2025 et la valeur exacte du code 5612Y."""
    import duckdb

    print("  Inspection du fichier (lecture des en-têtes)...")
    con = duckdb.connect()

    # Liste les colonnes
    cols = con.execute(f"""
        DESCRIBE SELECT * FROM read_csv_auto('{FICHIER_CSV_SOURCE}', sample_size=1000) LIMIT 1
    """).fetchall()

    nom_col = None
    for c in cols:
        if 'NAF25' in c[0] and 'Etablissement' in c[0]:
            nom_col = c[0]
            break

    if not nom_col:
        print("  [ERREUR] Colonne NAF 2025 introuvable dans le CSV.")
        print("  Le CSV ne contient peut-être pas la nouvelle variable NAF 2025.")
        print("  Colonnes contenant 'activite' :")
        for c in cols:
            if 'ctivit' in c[0].lower():
                print(f"      {c[0]}")
        return None, None

    print(f"  [OK] Colonne NAF 2025 détectée : {nom_col}")

    # Détecte les valeurs commençant par 5612 (passe le fichier en entier)
    print(f"  Recherche des codes 5612 dans la colonne... (3 à 10 min, soyez patient)")
    debut = time.time()
    valeurs = con.execute(f"""
        SELECT DISTINCT {nom_col} as code, COUNT(*) as n
        FROM read_csv_auto('{FICHIER_CSV_SOURCE}', sample_size=-1, ignore_errors=true)
        WHERE {nom_col} LIKE '%5612%' OR {nom_col} LIKE '%56.12%'
        GROUP BY {nom_col}
        ORDER BY n DESC
    """).fetchall()
    duree = time.time() - debut
    print(f"  [OK] Recherche terminée en {duree:.0f}s")

    if not valeurs:
        print("  [ERREUR] Aucune valeur 5612 trouvée dans le fichier.")
        return None, None

    print(f"  Codes 5612 détectés (tous statuts confondus) :")
    code_5612y = None
    for code, n in valeurs:
        marqueur = ""
        if code and '5612Y' in str(code).replace('.', '').upper():
            code_5612y = code
            marqueur = "  <- code 5612Y identifié"
        print(f"      {code} : {n:>10,} établissements{marqueur}")

    return nom_col, code_5612y


def filtrer_et_exporter(nom_col, code):
    """Filtre les food trucks actifs et écrit en CSV avec BOM UTF-8 pour Excel."""
    import duckdb

    print(f"  Filtrage en cours (code = {code}, état = actif)...")
    print(f"  Cette étape parcourt à nouveau le fichier complet (3 à 10 min)...")
    debut = time.time()

    con = duckdb.connect()
    con.execute(f"""
        COPY (
            SELECT *
            FROM read_csv_auto('{FICHIER_CSV_SOURCE}', sample_size=-1, ignore_errors=true)
            WHERE {nom_col} = '{code}'
              AND etatAdministratifEtablissement = 'A'
              AND statutDiffusionEtablissement != 'P'
        ) TO '{FICHIER_CSV_TEMP}' (HEADER, DELIMITER ';')
    """)

    duree = time.time() - debut
    print(f"  [OK] Filtrage terminé en {duree:.0f}s")

    # Ajout du BOM UTF-8 pour qu'Excel ouvre les accents correctement sur Windows
    print("  Conversion pour ouverture Excel (BOM UTF-8)...")
    with open(FICHIER_CSV_TEMP, 'rb') as f_in:
        contenu = f_in.read()
    with open(FICHIER_CSV_SORTIE, 'wb') as f_out:
        f_out.write(b'\xef\xbb\xbf' + contenu)
    os.remove(FICHIER_CSV_TEMP)

    taille_finale = Path(FICHIER_CSV_SORTIE).stat().st_size / 1e6
    print(f"  [OK] Fichier final : {FICHIER_CSV_SORTIE} ({taille_finale:.2f} Mo)")


def afficher_stats(nom_col, code):
    """Affiche les statistiques principales."""
    import duckdb
    con = duckdb.connect()

    print("\n  Statistiques :")
    res = con.execute(f"""
        SELECT 
            COUNT(*) as total,
            COUNT(DISTINCT siren) as nb_unites,
            COUNT(DISTINCT codeCommuneEtablissement) as nb_communes
        FROM read_csv_auto('{FICHIER_CSV_SOURCE}', sample_size=-1, ignore_errors=true)
        WHERE {nom_col} = '{code}'
          AND etatAdministratifEtablissement = 'A'
          AND statutDiffusionEtablissement != 'P'
    """).fetchone()

    print(f"      Total food trucks actifs       : {res[0]:>8,}")
    print(f"      Unités légales distinctes      : {res[1]:>8,}")
    print(f"      Communes différentes           : {res[2]:>8,}")

    # Top départements
    print("\n  Répartition par département (top 15) :")
    deps = con.execute(f"""
        SELECT 
            SUBSTRING(codeCommuneEtablissement, 1, 2) as dept,
            COUNT(*) as n
        FROM read_csv_auto('{FICHIER_CSV_SOURCE}', sample_size=-1, ignore_errors=true)
        WHERE {nom_col} = '{code}'
          AND etatAdministratifEtablissement = 'A'
          AND statutDiffusionEtablissement != 'P'
          AND codeCommuneEtablissement IS NOT NULL
        GROUP BY dept
        ORDER BY n DESC
        LIMIT 15
    """).fetchall()

    for dept, n in deps:
        print(f"      Dépt {dept} : {n:>6,} food trucks")


# ============================================================================
# PROGRAMME PRINCIPAL
# ============================================================================

def main():
    banniere("Extraction food trucks France - NAF 2025 code 5612Y")
    print("  Étude démographie food truck - wikifoodtruck.fr")
    print("  Mode : lecture directe du CSV local")

    # Étape 1 : vérification de DuckDB
    banniere("Étape 1/4 - Vérification de l'environnement")
    if not verifier_duckdb():
        sys.exit(1)

    # Étape 2 : vérification fichier source
    banniere("Étape 2/4 - Vérification du fichier source")
    if not verifier_fichier_source():
        sys.exit(1)

    # Étape 3 : détection du code
    banniere("Étape 3/4 - Identification du code 5612Y")
    nom_col, code = detecter_colonne_naf25()
    if not nom_col or not code:
        print("\n  [ERREUR] Impossible de continuer sans le code 5612Y.")
        sys.exit(1)

    # Étape 4 : filtrage et export
    banniere("Étape 4/4 - Filtrage et export CSV")
    filtrer_et_exporter(nom_col, code)

    # Statistiques rapides
    afficher_stats(nom_col, code)

    # Fin
    banniere("Terminé")
    print(f"  Fichier prêt à ouvrir dans Excel : {FICHIER_CSV_SORTIE}")
    print(f"  Emplacement : {Path(FICHIER_CSV_SORTIE).absolute()}")
    print()


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n  [INTERROMPU] Script arrêté par l'utilisateur.")
        sys.exit(1)
    except Exception as e:
        print(f"\n\n  [ERREUR INATTENDUE] {type(e).__name__}: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
