package com.smldb2.csvimporter;

import com.opencsv.CSVReader;
import java.io.FileReader;
import java.sql.*;
import java.util.HashSet;
import java.util.Set;

/**
 * Application Java standalone pour importer plusieurs CSV dans la base de données
 */
public class CsvImporter {

    // Configuration de la base de données
    private static final String DB_URL = "jdbc:mysql://localhost:3306/mybs?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "";

    // Chemins des fichiers CSV C:\csv
    private static final String CLIENTS_CSV = "C:/csv/clients.csv";
    private static final String STAT_ACT_ANN_CSV = "C:/csv/stat_act_ann.csv";
    private static final String STAT_ACT_DATE_CSV = "C:/csv/stat_act_date.csv";


    public static void main(String[] args) {
        System.out.println("🚀 Démarrage de l'import CSV...");
        System.out.println("========================================");

        CsvImporter importer = new CsvImporter();

        try {
            // Import des 3 fichiers CSV
            System.out.println("\n📁 Import du fichier CLIENTS...");
            importer.importClients();

            System.out.println("\n📁 Import du fichier STAT_ACT_ANN...");
            importer.importStatActAnn();

            System.out.println("\n📁 Import du fichier STAT_ACT_DATE...");
            importer.importStatActDate();

            System.out.println("\n========================================");
            System.out.println("✅ Tous les imports sont terminés avec succès!");
        } catch (Exception e) {
            System.err.println("❌ Erreur lors de l'import : " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * Import du fichier clients.csv
     */
    public void importClients() throws Exception {
        Connection conn = null;

        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            conn.setAutoCommit(false);

            System.out.println("📊 Connexion à la base de données établie");

            try (CSVReader reader = new CSVReader(new FileReader(CLIENTS_CSV))) {
                String[] line;
                reader.readNext(); // Ignorer l'en-tête

                Set<String> csvCodes = new HashSet<>();

                String checkQuery = "SELECT COUNT(*) FROM clients WHERE codeClt = ?";
                String updateQuery = "UPDATE clients SET description = ?, numContrat = ? WHERE codeClt = ?";
                String insertQuery = "INSERT INTO clients (codeClt, description, numContrat) VALUES (?, ?, ?)";

                PreparedStatement checkStmt = conn.prepareStatement(checkQuery);
                PreparedStatement updateStmt = conn.prepareStatement(updateQuery);
                PreparedStatement insertStmt = conn.prepareStatement(insertQuery);

                int insertCount = 0;
                int updateCount = 0;

                while ((line = reader.readNext()) != null) {
                    String codeClt = line[0].trim();
                    String description = line[1].trim();
                    String numContrat = line[2].trim();

                    csvCodes.add(codeClt);

                    checkStmt.setString(1, codeClt);
                    ResultSet rs = checkStmt.executeQuery();
                    rs.next();
                    boolean exists = rs.getInt(1) > 0;
                    rs.close();

                    if (exists) {
                        updateStmt.setString(1, description);
                        updateStmt.setString(2, numContrat);
                        updateStmt.setString(3, codeClt);
                        updateStmt.executeUpdate();
                        updateCount++;
                    } else {
                        insertStmt.setString(1, codeClt);
                        insertStmt.setString(2, description);
                        insertStmt.setString(3, numContrat);
                        insertStmt.executeUpdate();
                        insertCount++;
                    }
                }

                System.out.println("➕ Nouveaux clients ajoutés : " + insertCount);
                System.out.println("🔄 Clients mis à jour : " + updateCount);

                // Supprimer les clients qui ne sont plus dans le CSV
                String selectAllQuery = "SELECT codeClt FROM clients";
                Statement selectStmt = conn.createStatement();
                ResultSet allClients = selectStmt.executeQuery(selectAllQuery);

                String deleteQuery = "DELETE FROM clients WHERE codeClt = ?";
                PreparedStatement deleteStmt = conn.prepareStatement(deleteQuery);

                int deleteCount = 0;
                while (allClients.next()) {
                    String codeClt = allClients.getString("codeClt");
                    if (!csvCodes.contains(codeClt)) {
                        deleteStmt.setString(1, codeClt);
                        deleteStmt.executeUpdate();
                        deleteCount++;
                    }
                }

                System.out.println("🗑️ Clients supprimés : " + deleteCount);

                conn.commit();

                checkStmt.close();
                updateStmt.close();
                insertStmt.close();
                deleteStmt.close();
                selectStmt.close();
                allClients.close();
            }

        } catch (SQLException e) {
            if (conn != null) {
                try {
                    conn.rollback();
                    System.err.println("⚠️ Transaction annulée");
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
            throw e;
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                    System.out.println("🔌 Connexion fermée");
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Import du fichier stat_act_ann.csv
     * Colonnes attendues: année, codeSociete, acte, dépense, rembourser
     */
    public void importStatActAnn() throws Exception {
        Connection conn = null;

        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            conn.setAutoCommit(false);

            System.out.println("📊 Connexion à la base de données établie");

            try (CSVReader reader = new CSVReader(new FileReader(STAT_ACT_ANN_CSV))) {
                reader.readNext(); // Ignorer l'en-tête
                String[] line;

                // Supprimer toutes les données existantes
                String deleteAllQuery = "DELETE FROM stat_act_ann";
                Statement deleteStmt = conn.createStatement();
                int deletedRows = deleteStmt.executeUpdate(deleteAllQuery);
                System.out.println("🗑️ Anciennes données supprimées : " + deletedRows);
                deleteStmt.close();

                // Préparer l'insertion avec les colonnes correctes
                String insertQuery = "INSERT INTO stat_act_ann (annee, codesociete, acte, depense, rembourser) VALUES (?, ?, ?, ?, ?)";
                PreparedStatement insertStmt = conn.prepareStatement(insertQuery);

                int insertCount = 0;
                int errorCount = 0;

                while ((line = reader.readNext()) != null) {
                    try {
                        if (line.length >= 5) {
                            // année
                            String anneeStr = line[0].trim();
                            Integer annee = anneeStr.isEmpty() ? null : Integer.parseInt(anneeStr);

                            // codeSociete
                            String codeSociete = line[1].trim();

                            // acte
                            String acte = line[2].trim();

                            // dépense
                            String depenseStr = line[3].trim();
                            Double depense = depenseStr.isEmpty() ? null : Double.parseDouble(depenseStr.replace(",", "."));

                            // rembourser
                            String rembourserStr = line[4].trim();
                            Double rembourser = rembourserStr.isEmpty() ? null : Double.parseDouble(rembourserStr.replace(",", "."));

                            insertStmt.setObject(1, annee);
                            insertStmt.setString(2, codeSociete);
                            insertStmt.setString(3, acte);
                            insertStmt.setObject(4, depense);
                            insertStmt.setObject(5, rembourser);

                            insertStmt.executeUpdate();
                            insertCount++;

                            // Afficher la progression tous les 100 enregistrements
                            if (insertCount % 100 == 0) {
                                System.out.println("⏳ " + insertCount + " lignes traitées...");
                            }
                        }
                    } catch (Exception e) {
                        errorCount++;
                        System.err.println("⚠️ Erreur ligne " + (insertCount + errorCount) + " : " + e.getMessage());
                    }
                }

                System.out.println("➕ Lignes insérées avec succès : " + insertCount);
                if (errorCount > 0) {
                    System.out.println("❌ Lignes en erreur : " + errorCount);
                }

                conn.commit();
                insertStmt.close();
            }

        } catch (SQLException e) {
            if (conn != null) {
                try {
                    conn.rollback();
                    System.err.println("⚠️ Transaction annulée");
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
            throw e;
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                    System.out.println("🔌 Connexion fermée");
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * Import du fichier stat_act_date.csv
     * Colonnes attendues: date_bs, code_societe, acte, depense, rembourse, matricule
     */
    public void importStatActDate() throws Exception {
        Connection conn = null;

        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            conn.setAutoCommit(false);

            System.out.println("📊 Connexion à la base de données établie");

            try (CSVReader reader = new CSVReader(new FileReader(STAT_ACT_DATE_CSV))) {
                String[] headers = reader.readNext(); // Lire l'en-tête
                String[] line;

                System.out.println("📋 Colonnes détectées : " + String.join(", ", headers));

                // Supprimer toutes les données existantes
                String deleteAllQuery = "DELETE FROM stat_act_date";
                Statement deleteStmt = conn.createStatement();
                int deletedRows = deleteStmt.executeUpdate(deleteAllQuery);
                System.out.println("🗑️ Anciennes données supprimées : " + deletedRows);
                deleteStmt.close();

                // Vérifier si les colonnes correspondent au format attendu
                boolean formatCorrect = headers.length >= 6 &&
                        headers[0].trim().equalsIgnoreCase("date_bs") &&
                        headers[1].trim().equalsIgnoreCase("code_societe") &&
                        headers[2].trim().equalsIgnoreCase("acte") &&
                        headers[3].trim().equalsIgnoreCase("depense") &&
                        headers[4].trim().equalsIgnoreCase("rembourse") &&
                        headers[5].trim().equalsIgnoreCase("matricule");

                String insertQuery;

                if (formatCorrect) {
                    // Format attendu: utiliser les noms de colonnes fixes
                    insertQuery = "INSERT INTO stat_act_date (date_bs, code_societe, acte, depense, rembourse, matricule) VALUES (?, ?, ?, ?, ?, ?)";
                    System.out.println("✅ Format CSV correct détecté");
                } else {
                    // Format dynamique basé sur les en-têtes du CSV
                    System.out.println("⚠️ Format CSV différent, utilisation du format dynamique");
                    StringBuilder insertQueryBuilder = new StringBuilder("INSERT INTO stat_act_date (");
                    StringBuilder valuesQuery = new StringBuilder(" VALUES (");

                    for (int i = 0; i < headers.length; i++) {
                        if (i > 0) {
                            insertQueryBuilder.append(", ");
                            valuesQuery.append(", ");
                        }
                        insertQueryBuilder.append("`").append(headers[i].trim()).append("`");
                        valuesQuery.append("?");
                    }
                    insertQueryBuilder.append(")");
                    valuesQuery.append(")");

                    insertQuery = insertQueryBuilder.toString() + valuesQuery.toString();
                }

                System.out.println("📝 Requête SQL : " + insertQuery);

                PreparedStatement insertStmt = conn.prepareStatement(insertQuery);

                int insertCount = 0;
                int errorCount = 0;

                while ((line = reader.readNext()) != null) {
                    try {
                        if (line.length >= headers.length) {
                            for (int i = 0; i < headers.length; i++) {
                                String value = line[i].trim();
                                // Remplacer les virgules par des points pour les nombres
                                if (i == 3 || i == 4) { // depense et rembourse
                                    value = value.replace(",", ".");
                                }
                                insertStmt.setString(i + 1, value);
                            }
                            insertStmt.executeUpdate();
                            insertCount++;

                            // Afficher la progression tous les 500 enregistrements
                            if (insertCount % 500 == 0) {
                                System.out.println("⏳ " + insertCount + " lignes traitées...");
                            }
                        } else {
                            errorCount++;
                            System.err.println("⚠️ Ligne " + (insertCount + errorCount) + " ignorée : nombre de colonnes insuffisant");
                        }
                    } catch (Exception e) {
                        errorCount++;
                        System.err.println("⚠️ Erreur ligne " + (insertCount + errorCount) + " : " + e.getMessage());
                        // Continuer avec la ligne suivante
                    }
                }

                System.out.println("➕ Lignes insérées avec succès : " + insertCount);
                if (errorCount > 0) {
                    System.out.println("❌ Lignes en erreur : " + errorCount);
                }

                conn.commit();
                insertStmt.close();
            }

        } catch (SQLException e) {
            if (conn != null) {
                try {
                    conn.rollback();
                    System.err.println("⚠️ Transaction annulée");
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
            throw e;
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                    System.out.println("🔌 Connexion fermée");
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}