package application;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.converter.IntegerStringConverter;

import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;




public class MainController implements Initializable {
	
	@FXML
	private TableView<Personne> tablePersonnes;
	
	@FXML
	private TableColumn<Personne, Integer> colonneId;
	
	@FXML
	private TableColumn<Personne, String> colonneNom;
	
	@FXML
	private TableColumn<Personne, String> colonnePrenom;
	
	@FXML
	private TableColumn<Personne, Integer> colonneAge;
	
	@FXML
	private Button buttonAjouter;
	
	@FXML
	private Button buttonModifier;
	
	@FXML
	private Button buttonSupprimer;
	
	private ObservableList<Personne> personnes;
	
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		personnes = FXCollections.observableArrayList();
		
		// Configuration des colonnes pour l'affichage
		colonneId.setCellValueFactory(new PropertyValueFactory<>("id"));
		colonneNom.setCellValueFactory(new PropertyValueFactory<>("nom"));
		colonnePrenom.setCellValueFactory(new PropertyValueFactory<>("prenom"));
		colonneAge.setCellValueFactory(new PropertyValueFactory<>("age"));
		
		// Édition en cellule : double-clic sur une cellule pour éditer
		colonneNom.setCellFactory(TextFieldTableCell.forTableColumn());
		colonneNom.setOnEditCommit(event -> {
			Personne personne = event.getRowValue();
			personne.setNom(event.getNewValue());
			updatePersonneInDB(personne); // Synchronisation avec la BDD
		});
		
		colonnePrenom.setCellFactory(TextFieldTableCell.forTableColumn());
		colonnePrenom.setOnEditCommit(event -> {
			Personne personne = event.getRowValue();
			personne.setPrenom(event.getNewValue());
			updatePersonneInDB(personne); // Synchronisation avec la BDD
		});
		
		// Édition de l'âge avec validation (conversion String -> Integer)
		colonneAge.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter()));
		colonneAge.setOnEditCommit(event -> {
			Personne personne = event.getRowValue();
			try {
				int newAge = event.getNewValue();
				if (newAge >= 0 && newAge <= 150) {
					personne.setAge(newAge);
					updatePersonneInDB(personne); // Synchronisation avec la BDD
				} else {
					Alert alert = new Alert(Alert.AlertType.ERROR);
					alert.setTitle("Erreur");
					alert.setHeaderText("Âge invalide");
					alert.setContentText("L'âge doit être entre 0 et 150.");
					alert.showAndWait();
					tablePersonnes.refresh();
				}
			} catch (Exception e) {
				Alert alert = new Alert(Alert.AlertType.ERROR);
				alert.setTitle("Erreur");
				alert.setHeaderText("Valeur invalide");
				alert.setContentText("L'âge doit être un nombre valide.");
				alert.showAndWait();
				tablePersonnes.refresh();
			}
		});
		
		tablePersonnes.setEditable(true);
		
		
		tablePersonnes.setItems(personnes);
		
		// Charger les données depuis la base de données
		loadPersonnesFromDB();
	}
	
	// Charge toutes les personnes depuis la base de données
	private void loadPersonnesFromDB() {
		String sql = "SELECT id, nom, prenom, age FROM personne ORDER BY id";
		
		try (Connection conn = DbConnexion.getConnection();
			 Statement stmt = conn.createStatement();
			 ResultSet rs = stmt.executeQuery(sql)) {
			
			personnes.clear();
			
			while (rs.next()) {
				int id = rs.getInt("id");
				String nom = rs.getString("nom");
				String prenom = rs.getString("prenom");
				int age = rs.getInt("age");
				
				personnes.add(new Personne(id, nom, prenom, age));
			}
			
		} catch (SQLException e) {
			showError("Erreur de chargement", "Impossible de charger les données depuis la base de données.\n" + e.getMessage());
			e.printStackTrace();
		}
	}
	
	// Insère une nouvelle personne dans la base de données
	// L'ID est généré automatiquement par MySQL (AUTO_INCREMENT)
	private void insertPersonneInDB(Personne personne) {
		// Ne pas spécifier l'ID dans l'INSERT - MySQL le génère automatiquement
		String sql = "INSERT INTO personne (nom, prenom, age) VALUES (?, ?, ?)";
		
		try (Connection conn = DbConnexion.getConnection();
			 PreparedStatement pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
			
			pstmt.setString(1, personne.getNom());
			pstmt.setString(2, personne.getPrenom());
			pstmt.setInt(3, personne.getAge());
			
			int affectedRows = pstmt.executeUpdate();
			
			if (affectedRows > 0) {
				ResultSet generatedKeys = pstmt.getGeneratedKeys();
				if (generatedKeys.next()) {
					// Récupère l'ID auto-généré par MySQL et le définit dans l'objet
					personne.setId(generatedKeys.getInt(1));
				}
			}
			
		} catch (SQLException e) {
			showError("Erreur d'insertion", "Impossible d'ajouter la personne dans la base de données.\n" + e.getMessage());
			e.printStackTrace();
		}
	}
	
	// Met à jour une personne dans la base de données
	private void updatePersonneInDB(Personne personne) {
		String sql = "UPDATE personne SET nom = ?, prenom = ?, age = ? WHERE id = ?";
		
		try (Connection conn = DbConnexion.getConnection();
			 PreparedStatement pstmt = conn.prepareStatement(sql)) {
			
			pstmt.setString(1, personne.getNom());
			pstmt.setString(2, personne.getPrenom());
			pstmt.setInt(3, personne.getAge());
			pstmt.setInt(4, personne.getId());
			
			pstmt.executeUpdate();
			
		} catch (SQLException e) {
			showError("Erreur de mise à jour", "Impossible de mettre à jour la personne dans la base de données.\n" + e.getMessage());
			e.printStackTrace();
			loadPersonnesFromDB(); // Recharger en cas d'erreur
		}
	}
	
	// Supprime une personne de la base de données
	private void deletePersonneFromDB(int id) {
		String sql = "DELETE FROM personne WHERE id = ?";
		
		try (Connection conn = DbConnexion.getConnection();
			 PreparedStatement pstmt = conn.prepareStatement(sql)) {
			
			pstmt.setInt(1, id);
			pstmt.executeUpdate();
			
		} catch (SQLException e) {
			showError("Erreur de suppression", "Impossible de supprimer la personne de la base de données.\n" + e.getMessage());
			e.printStackTrace();
		}
	}
	
	@FXML
	private void handleAjouter() {
		// Crée une nouvelle personne sans ID (ID sera généré par MySQL)
		Personne nouvellePersonne = new Personne();
		
		boolean okClicked = showPersonneEditDialog(nouvellePersonne, true);
		
		if (okClicked) {
			insertPersonneInDB(nouvellePersonne); // Insère dans la BDD (ID auto-généré)
			personnes.add(nouvellePersonne); // Ajoute à la liste (ID déjà mis à jour par MySQL)
		}
	}
	
	@FXML
	private void handleModifier() {
		Personne personneSelectionnee = tablePersonnes.getSelectionModel().getSelectedItem();
		
		
		if (personneSelectionnee != null) {
			boolean okClicked = showPersonneEditDialog(personneSelectionnee, false);
			if (okClicked) {
				updatePersonneInDB(personneSelectionnee); // Met à jour dans la BDD
				tablePersonnes.refresh();
			}
		} else {
			Alert alert = new Alert(Alert.AlertType.WARNING);
			alert.setTitle("Aucune sélection");
			alert.setHeaderText("Aucune personne sélectionnée");
			alert.setContentText("Veuillez sélectionner une personne dans la table.");
			alert.showAndWait();
		}
	}
	
	@FXML
	private void handleSupprimer() {
		int selectedIndex = tablePersonnes.getSelectionModel().getSelectedIndex();
		if (selectedIndex >= 0) {
			Personne personne = tablePersonnes.getSelectionModel().getSelectedItem();
			Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
			alert.setTitle("Confirmation");
			alert.setHeaderText("Supprimer la personne");
			alert.setContentText("Êtes-vous sûr de vouloir supprimer " + personne.getNom() + " " + personne.getPrenom() + " ?");
			
			// Lambda : exécute la suppression seulement si l'utilisateur confirme
			alert.showAndWait().ifPresent(response -> {
				if (response == ButtonType.OK) {
					deletePersonneFromDB(personne.getId()); // Supprime de la BDD
					personnes.remove(selectedIndex);
				}
			});
		} else {
			Alert alert = new Alert(Alert.AlertType.WARNING);
			alert.setTitle("Aucune sélection");
			alert.setHeaderText("Aucune personne sélectionnée");
			alert.setContentText("Veuillez sélectionner une personne dans la table.");
			alert.showAndWait();
		}
	}
	
	// Crée et affiche une fenêtre modale pour éditer une personne
	private boolean showPersonneEditDialog(Personne personne, boolean isNew) {
		try {
			FXMLLoader loader = new FXMLLoader();
			loader.setLocation(getClass().getResource("personneForm.fxml"));
			VBox page = loader.load();
			
		//	VBox page = FXMLLoader.load(getClass().getResource("personneForm.fxml"));
			
			Stage dialogStage = new Stage();
			dialogStage.setTitle(isNew ? "Nouvelle Personne" : "Modifier Personne");
			dialogStage.initModality(Modality.WINDOW_MODAL); // Bloque la fenêtre principale
			dialogStage.initOwner(tablePersonnes.getScene().getWindow());
			Scene scene = new Scene(page);
			dialogStage.setScene(scene);
			
			PersonneFormController controller = loader.getController();
			controller.setDialogStage(dialogStage);
			controller.setPersonne(personne);
			
			dialogStage.showAndWait(); // Attend la fermeture de la fenêtre
			
			return controller.isOkClicked();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	
	// Affiche un message d'erreur
	private void showError(String title, String message) {
		Alert alert = new Alert(Alert.AlertType.ERROR);
		alert.setTitle(title);
		alert.setHeaderText(null);
		alert.setContentText(message);
		alert.showAndWait();
	}
	
	public ObservableList<Personne> getPersonnes() {
		return personnes;
	}
}
