<?php
    require("./models/project_model.php");
    require("./entities/project_entity.php");
    require("./models/category_model.php");
    require("./entities/category_entity.php");
    require("./models/image_model.php");
    require("./entities/image_entity.php");
    require("./models/user_model.php");
    require("./entities/user_entity.php");
    require("mother_controller.php");
    use PHPMailer\PHPMailer\PHPMailer;
	use PHPMailer\PHPMailer\Exception;
	use PHPMailer\PHPMailer\SMTP;

    /**
     * Le controler des Project
     * @author Yasser & Laura
     */
    class ProjectCtrl extends MotherCtrl{

        /**
         * Fonction d'affichage de la page d'acceuil
         */

        public function home(){


			if (!isset($_SESSION['user']) && isset($_COOKIE['remember_me'])) {
        
        		$token_du_cookie = $_COOKIE['remember_me'];
        		$hash_a_verifier = hash('sha256', $token_du_cookie);

				$objUserModel = new UserModel;
        		// 2. On cherche le jeton dans TA table "tokens" (avec token_user_id)
        		$row = $objUserModel->getTokenUser($hash_a_verifier);

        		if ($row) {
        		    // 3. Jeton trouvé ! On récupère les infos de l'utilisateur
        		    $user = $objUserModel->findUserById($row['token_user_id']);

        		    if ($user) {
        		        // 4. On recrée la session comme lors d'un login normal
        		        $_SESSION['user'] = $user;
        		    }
        		}
    		}	


			$intCategory = 0; 
			if (!empty($_GET['filter_cat'])) {
				$intCategory = (int) $_GET['filter_cat'];
			}

			$boolOld = false;
			if (!empty($_GET['filter_old']) && $_GET['filter_old'] == 'true') {
				$boolOld = true;
			}
            
            $objProjectModel 	= new ProjectModel;
            $arrProject		    = $objProjectModel->findAll(0,'',0,0,'','','',$intCategory,$boolOld);
            $arrProjectToDisplay = array();
            foreach($arrProject as $arrDetProject){
                $objProject = new Project;
                $objProject->hydrate($arrDetProject);
                $arrProjectToDisplay[] = $objProject;
            }

            $this->_arrData['arrProjectToDisplay']  = $arrProjectToDisplay;
			$this->_display("home");

        }

        /**
         * Fonction d'affichage de la barre de recherche
         */
        public function search(){

            //Récupérer les informations du formulaire
                $strKeywords 	= $_POST['keywords']??'';
                $intAuthor		= $_POST['author']??0;
                $intPeriod		= $_POST['period']??0;
                $strDate		= $_POST['date']??'';
                $strStartDate	= $_POST['startdate']??'';
                $strEndDate		= $_POST['enddate']??'';
                $intCategory	= $_POST['category']??0;

            // Récupération des projets
            $objProjectModel    = new ProjectModel;
            $arrProject         = $objProjectModel->findAll(intAuthor:$intAuthor, intPeriod:$intPeriod, strDate:$strDate, 
							    strKeywords:$strKeywords, strStartDate:$strStartDate, strEndDate:$strEndDate, intCategory:$intCategory);
            $arrProjectToDisplay    = array(); 

            foreach($arrProject as $arrDetProject){
                $objProject = new Project;
                $objProject->hydrate($arrDetProject);
                $arrProjectToDisplay[]  = $objProject;
            }
        
            // Récupération des utilisateurs
            $objUserModel   = new UserModel;
            $arrUser        = $objUserModel->findAllUsers();

            // Récupération des catégories
            $objCategoryModel   = new CategoryModel;
            $arrCategory        = $objCategoryModel->findAllCategory();

            $this->_arrData['arrProjectToDisplay']  = $arrProjectToDisplay;
            $this->_arrData['arrCategory']  = $arrCategory;
            $this->_arrData['arrProject']  = $arrProject;
            $this->_arrData['arrUser']  = $arrUser;

            $this->_display("search");
        }

        /**
         * Fonction d'affichage de la page projet
		 * @author Christel adapter par Guillaume
         */
		public function addedit_project(){
			if (!isset($_SESSION['user'])){ // Pas d'utilisateur connecté
				header("Location:index.php?ctrl=error&action=error_403");
				exit;
			}
			
			$objProject         = new Project;
			$objProjectModel    = new ProjectModel;
			$objCategoryModel   = new CategoryModel;
			
			// Dans la cas de modif
			if (isset($_GET['id'])){
				$arrProject = $objProjectModel->findOne($_GET['id']);
				$objProject->hydrate($arrProject); // BDD
				$this->_arrData['arrImages'] = $objProjectModel->getImagesByProjectId($objProject->getId());
			}
			
			// Tester le formulaire
			$arrError = [];
			if (count($_POST) > 0) {
				
				$objProject->hydrate($_POST); // Formulaire
				if ($objProject->getTitle() == ""){
					$arrError['title'] = "Le titre est obligatoire";
				}
				
				if ($objProject->getDescription() == ""){
					$arrError['description'] = "La description est obligatoire";
				}
				
				if ($objProject->getContent() == ""){
					$arrError['content'] = "Le contenu est obligatoire";
				}   
				
				// Vérification de l'image (Thumbnail)
				$arrTypeAllowed = array('image/jpeg', 'image/png', 'image/webp');
				if ($_FILES['thumbnail']['error'] != 4){ 
					if (!in_array($_FILES['thumbnail']['type'], $arrTypeAllowed)){
						$arrError['thumbnail'] = "Le type de fichier n'est pas autorisé";
					}else{
						switch ($_FILES['thumbnail']['error']){
							case 0 : 
								$strImageName = uniqid().".webp";
								$strOldImg    = $objProject->getThumbnail();
								$objProject->setThumbnail($strImageName);
								break;
							case 1 :
								$arrError['thumbnail'] = "Le fichier est trop volumineux";
								break;
							case 2 :
								$arrError['thumbnail'] = "Le fichier est trop volumineux";
								break;
							case 3 :
								$arrError['thumbnail'] = "Le fichier a été partiellement téléchargé";
								break;
							case 6 :
								$arrError['thumbnail'] = "Le répertoire temporaire est manquant";
								break;
							default :
								$arrError['thumbnail'] = "Erreur sur l'image";
								break;
						}
					}
				}else{
					if (is_null($objProject->getThumbnail())){ 
						$arrError['thumbnail'] = "L'image est obligatoire";
					}
				}

				// SI pas d'erreur : on traite l'image principale
				if (count($arrError) == 0){

					$boolImageOk = true;
					
					// On peux changer ces dimensions si on veux que la miniature soit plus grande/petite
					if (isset($strImageName)){
						$strDest    = $_ENV['IMG_PROJECT_PATH'].$strImageName;
						$strSource  = $_FILES['thumbnail']['tmp_name'];
						list($intWidth, $intHeight) = getimagesize($strSource);
						
						// Redimensionnement de la Thumbnail
						$intDestWidth = 200; $intDestHeight = 250;
						$fltDestRatio = $intDestWidth / $intDestHeight;
						$fltSourceRatio = $intWidth / $intHeight;
						
						if ($fltSourceRatio > $fltDestRatio) {
							$intCropHeight = $intHeight;
							$intCropWidth = (int)round($intHeight * $fltDestRatio);
							$intCropX = (int)(($intWidth - $intCropWidth) / 2);
							$intCropY = 0;
						} else {
							$intCropWidth = $intWidth;
							$intCropHeight = (int)round($intWidth / $fltDestRatio);
							$intCropX = 0;
							$intCropY = (int)(($intHeight - $intCropHeight) / 2);
						}
						
						$objDest = imagecreatetruecolor($intDestWidth, $intDestHeight); 
						switch ($_FILES['thumbnail']['type']) {
							case 'image/jpeg' : 
								$objSource = imagecreatefromjpeg($strSource); 
								break;
							case 'image/png'  : 
								$objSource = imagecreatefrompng($strSource); 
								break;
							case 'image/webp' : 
								$objSource = imagecreatefromwebp($strSource); 
								break;
						}
						
						imagecopyresampled($objDest, $objSource, 0, 0, $intCropX, $intCropY, $intDestWidth, $intDestHeight, $intCropWidth, $intCropHeight);
						$boolImageOk = imagewebp($objDest, $strDest);
						
						//Suppression des doublons pour la mémoire vive
						imagedestroy($objDest);
						imagedestroy($objSource);
					}

					// SI image ok, on balance tout dans la bdd
					if ($boolImageOk){
						if (!isset($_GET['id'])){
							$objProject->setUser_id($_SESSION['user']['user_id']);
							$boolOk = $objProjectModel->insert($objProject);
						} else {
							$boolOk = $objProjectModel->updateProject($objProject);
						}
						
						// Gestion des 20 Images après l'envoie de la Thumbnail en BDD
						if ($boolOk){
							//Si pas d'erreur 
							if (isset($_FILES['imageProject']) && $_FILES['imageProject']['error'][0] != 4) {
								$files = $_FILES['imageProject'];
								$maxPhotos = 20;

								// 1. On compte combien d'images le projet possède déjà en BDD
								$currentImages = $objProjectModel->getImagesByProjectId($objProject->getId());
								$totalExisting = count($currentImages);

								// 2. On calcule combien de photos on peut encore ajouter
								$remainingSlots = $maxPhotos - $totalExisting;

								// Si on a déjà atteint ou dépassé la limite, on ne traite même pas les fichiers
								if ($remainingSlots <= 0) {
									$_SESSION['error'] = "Limite de $maxPhotos photos atteinte. Supprimez-en pour en ajouter de nouvelles.";
								} else {
									$uploadedCount = 0;

									foreach ($files['name'] as $key => $name) {
										// 3. On utilise le quota restant comme condition d'arrêt
										if ($uploadedCount >= $remainingSlots) break;

										if ($files['error'][$key] === 0 && in_array($files['type'][$key], $arrTypeAllowed)) {
											
											$galleryName = uniqid() . "_gallery.webp";
											$strDestGallery = $_ENV['IMG_PROJECT_PATH'].$galleryName;
											$strSourceGallery = $files['tmp_name'][$key];

											// Reprise de la logique de redimensionnement
											list($intW, $intH) = getimagesize($strSourceGallery);
											
											// On peux changer ces dimensions si on veux que la galerie soit plus grande/petite
											$intDestW = 150; $intDestH = 150; 
											$fltDestR = $intDestW / $intDestH;
											$fltSourceR = $intW / $intH;
											
											if ($fltSourceR > $fltDestR) {
												$intCropH = $intH;
												$intCropW = (int)round($intH * $fltDestR);
												$intCropX = (int)(($intW - $intCropW) / 2);
												$intCropY = 0;
											} else {
												$intCropW = $intW;
												$intCropH = (int)round($intW / $fltDestR);
												$intCropX = 0;
												$intCropY = (int)(($intH - $intCropH) / 2);
											}
											
											$objDestGallery = imagecreatetruecolor($intDestW, $intDestH); 
											
											// Création de la source selon le type de chaque image de la boucle
											switch ($files['type'][$key]) {
												case 'image/jpeg' : 
													$objSourceGallery = imagecreatefromjpeg($strSourceGallery); 
													break;
												case 'image/png'  : 
													$objSourceGallery = imagecreatefrompng($strSourceGallery); 
													break;
												case 'image/webp' : 
													$objSourceGallery = imagecreatefromwebp($strSourceGallery);
													break;
											}

											if ($objSourceGallery) {
												imagecopyresampled($objDestGallery, $objSourceGallery, 0, 0, $intCropX, $intCropY, $intDestW, $intDestH, $intCropW, $intCropH);
												
												if (imagewebp($objDestGallery, $strDestGallery)) {
													// Insertion en BDD
													$objProjectModel->addImageInProject($galleryName, $objProject->getId());
													$uploadedCount++;
												}
												
												imagedestroy($objDestGallery);
												imagedestroy($objSourceGallery);
											}
										}
									}

									if ($uploadedCount > 0) {
										$_SESSION['success'] = "$uploadedCount image(s) ajoutée(s) à la galerie !";
									}
								}
							}
							
							// Suppression de l'ancienne miniature 
							if(isset($strOldImg) && !empty($strOldImg) && isset($strImageName)){
								$strOldFile = $_ENV['IMG_PROJECT_PATH'].$strOldImg;
								if (file_exists($strOldFile)) unlink($strOldFile);
							}

							$_SESSION['success'] = (!isset($_GET['id'])) ? "Le projet a bien été créé" : "Le projet a bien été modifié";
							header("Location:index.php");
							exit;
						} else {
							$arrError[] = "Erreur lors de l'enregistrement en base de données";
						}
					} else {
						$arrError['thumbnail'] = "Erreur dans le traitement de l'image";
					}
				}
			}
			
			// Données pour la vue
			$this->_arrData['arrCategory'] = $objCategoryModel->findAllCategory();
			$this->_arrData['objProject']  = $objProject; 
			$this->_arrData['arrError']    = $arrError;

			// Si on est en modifications de projet, on récupère les images pour les afficher dans le formulaire
			if ($objProject->getId()) {
				// On récupère les images via le modèle et on les stocke dans le tableau de données
				$this->_arrData['arrImages'] = $objProjectModel->getImagesByProjectId($objProject->getId());
			} else {
				// Sinon on initialise un tableau vide pour éviter que Smarty ne râle
				$this->_arrData['arrImages'] = [];
			}

			$this->_display('addedit_project');
		}
		
		/** 
		* Fonction d'affichage de projet
		*/
        public function display() {
			$intId = $_GET['id'] ?? null;

			if ($intId) {
				$objProjectModel = new ProjectModel();
				$arrProject = $objProjectModel->findOne((int)$intId);
				
				// CORRECTION ICI : on utilise $intId (pas $id)
				$arrImages = $objProjectModel->getImagesByProjectId((int)$intId);
				
				if ($arrProject) {
					$objProject = new Project();
					$objProject->hydrate($arrProject);
					
					$this->_arrData["arrProject"] = $arrProject;
					$this->_arrData["objProject"] = $objProject;
					$this->_arrData["arrImages"] = $arrImages; 

					$this->_display("project_display");
					
				} else {
					header("Location: index.php?ctrl=project&action=home");
					exit;
				}
			} else {
				header("Location: index.php?ctrl=project&action=home");
				exit;
			}
		}
		
		/** 
		* Fonction de partage de projet
		*/
		public function shareProject(){
			if (count($_POST) > 0)
			{
				$projectId = (int)($_POST['project_id'] ?? 0);
				$toEmail   = trim($_POST['to_email'] ?? '');
 
				$objProjectModel = new ProjectModel();
				$arrProject = $objProjectModel->findOne($projectId);
 
				if (!$arrProject) {
					header("Location: index.php?ctrl=project&action=home");
					exit;
				}
 
				$objProject = new Project();
				$objProject->hydrate($arrProject);
 
				$objMail = new PHPMailer();
				$objMail->IsSMTP();
				$objMail->Mailer    = "smtp";
				$objMail->CharSet   = PHPMailer::CHARSET_UTF8;
				$objMail->SMTPDebug = 0;   				
 
				$objMail->SMTPAuth   = true;
				$objMail->SMTPSecure = "tls";
				$objMail->Port       = 587;
				$objMail->Host       = 'smtp-relay.brevo.com';
				$objMail->Username   = 'a2a67e001@smtp-brevo.com';
				$objMail->Password   = 'xsmtpsib-f2af87e12d3db6f1b99802a92c1acda32d45fc32a8446eeed7e49ec91c4ec7ef-AX8Y7YkRWYSmKHwS';
 
				// Désactive la vérification du certificat SSL 
				// Cela permet d'éviter les erreurs liées au certificat, mais réduit la sécurité de la connexion.
				$objMail->SMTPOptions = [
					'ssl' => [
						'verify_peer'       => false,						
					],
				];
 
 
				$objMail->IsHTML(true);
 
				$objMail->setFrom('projet.folliow@hotmail.com', 'Folliow');
				$objMail->addAddress($toEmail);
 
				$objMail->Subject = "Projet : " . $objProject->getTitle();
 
				$url = "https://php.boulayoune.com/index.php?ctrl=project&action=display&id=" . $projectId;
 
				$this->_arrData['projectTitle']       = $objProject->getTitle();
				$this->_arrData['projectDescription'] = $objProject->getDescription();
				$this->_arrData['projectUrl']         = $url;
 
				$objMail->Body = $this->_display("mail_message", false);
 
				if ($objMail->Send()) {
					header("Location: index.php?ctrl=project&action=display&id=".$projectId."&mail=ok");
				} else {
					header("Location: index.php?ctrl=project&action=display&id=".$projectId."&mail=fail");
				}
				exit;
			}
 
			header("Location: index.php?ctrl=project&action=home");
			exit;
		}
		
		/** 
		* Fonction de modération de projet = accepté
		* @author Guillaume
		*/
		public function accept(){

			//Récupéré l'id dans l'url
			$intId = $_GET['id'];

			//Je créer un nouveau model pour exec la commande SQL
			$objProjectModel = new ProjectModel;
			$objProjectModel->accept($intId);

			//Redirection vers la page 
			header("Location: index.php");
			exit;
		}
		
		/** 
		* Fonction de modération de projet = refusé
		* @author Guillaume
		*/
		public function refuse(){

			//Récupéré l'id dans l'url
			$intId = $_GET['id'];

			//Je créer un nouveau model pour exec la commande SQL
			$objProjectModel = new ProjectModel;
			$objProjectModel->refuse($intId);

			//Redirection vers la page 
			header("Location: index.php");
			exit;
		}
		
		/** 
		* Fonction de suppression de projet
		* @author Guillaume
		*/
		public function delete(){
			//Vérif utilisateur soit bien modérateur
			if (!isset($_SESSION['user']) || $_SESSION['user']['user_status'] != 2) {
				header("Location: index.php");
				exit;
			}	
			
			$intId = $_GET['id'] ?? null;

			if ($intId) {
				$objProjectModel = new ProjectModel();
				if ($objProjectModel->delete_soft_project((int) $intId)) {
					$_SESSION['success'] = "Le projet a été archivé avec succès.";
				} else {
					$_SESSION['error'] = "Une erreur est survenue lors de l'archivage.";
				}
			}

			//Redirection vers la page 
			header("Location: index.php");
			exit;
		}
		
		/**
		* Fonction de changement de statut (Approuvé, Refusé, En attente)
		* @author Guillaume 
		*/
		public function change_image_status() {
			if (isset($_GET['id_img']) && isset($_GET['status'])) {
				$idImg  = (int)$_GET['id_img'];
				$status = $_GET['status']; // "en_attente" passage à "approuvé"
				
				$objProjectModel = new ProjectModel();
				
				// On passe le statut texte directement à ta méthode de modèle
				if ($objProjectModel->updateImageStatus($idImg, $status)) {
					$_SESSION['success'] = "Le statut de l'image est désormais : " . ucfirst($status);
				}
			}
			
			// La redirection : Si on sait d'où on vient, on y retourne, sinon index
			$urlRedirect = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "index.php";
			header("Location: " . $urlRedirect);
			exit;
		}
		
		
		/** 
		* Fonction de validation de l'image de projet 
		* @author Guillaume
		*/
		public function delete_image() {
			// Vérifier l'id de l'image
			$idImg = $_GET['id_img'];
			$objProjectModel = new ProjectModel();
			
			// Récupérer le nom du fichier pour le supprimer physiquement
			$image = $objProjectModel->findImage($idImg);
			if ($image) {
				$filePath = $_ENV['IMG_PROJECT_PATH'] . $image['image_name'];
				if (file_exists($filePath)) unlink($filePath);
				
				$objProjectModel->deleteImage($idImg);
				$_SESSION['success'] = "Image supprimée !";
			}
			
			// La redirection : Si on sait d'où on vient, on y retourne, sinon index
			$url = (isset($_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] : "index.php";
			header("Location: " . $url);
			exit;
		}
		
		
		/**
		* Fonction d'ajout des 20 images max du projet
		* @author Guillaume
		* @param string $fileName = le nom de l'image, int $projectId = L'Id du projet que l'on veut afficher, string $alt = qui affichera pars défaut "Image de projet"
		* @return bool Est-ce que la requête s'est bien passée
		*/
		public function addImageInProject(string $fileName, int $projectId, string $alt = "Image de projet"): bool {
			$strRq = "INSERT INTO image (
						image_name, 
						image_alt, 
						image_status, 
						image_project
					  ) 
					  VALUES (:name, :alt, :status, :project)";
			
			$rqPrep = $this->_db->prepare($strRq);
			
			$rqPrep->bindValue(":name", $fileName, PDO::PARAM_STR);
			$rqPrep->bindValue(":alt", $alt, PDO::PARAM_STR);
			$rqPrep->bindValue(":status", "en_attente", PDO::PARAM_STR); // Valeur string en brute
			$rqPrep->bindValue(":project", $projectId, PDO::PARAM_INT);
			
			return $rqPrep->execute();
		}	
		
		/**
		* Fonction d'affichage des 20 images max du projet
		* @author Guillaume
		* @param array $ProjectId L'Id du projet que l'on veut afficher
		* @return bool Est-ce que la requête s'est bien passée
		*/
		public function getImagesByProjectId(int $projectId): array {
			$strRq = "SELECT image_id, image_name, image_alt, image_status 
					  FROM image 
					  WHERE image_project = :id";
			
			$rqPrep = $this->_db->prepare($strRq);
			$rqPrep->bindValue(":id", $projectId, PDO::PARAM_INT);
			$rqPrep->execute();
			
			return $rqPrep->fetchAll(PDO::FETCH_ASSOC);
		}
		
		/** 
		* Page mentions légales 
		*/
		public function mentions(){
			// Afficher
			$this->_display("mentions");
		}
			
		/** 
		* Page à propos
		*/
		public function about(){
			// Afficher
			$this->_display("about");
		}
				
    }
