<?php
namespace Controleur;
use Gateway\CharacterGateway;
use Gateway\SourceGateway;
use Model\CharacterModel;
use Model\CommentaryModel;
use Gateway\CommentaryGateway;
use Model\SourceModel;
use Model\UserModel;
use Gateway\UserGateway;
use Model\QuoteModel;
use Gateway\QuoteGateway;
use Gateway\QuestionGateway;
use Gateway\QuizGateway;
use Gateway\QuizQuestionGateway;
use Model\QuestionModel;
use Model\QuizModel;
use Model\QuizQuestionModel;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Verification\Verification;
use Enum\TypeSourceEnum;
use Model\ImageModel;
use Gateway\ImageGateway;

class UserControler {

    private CommentaryModel $cMod;
    private UserModel $uMod;
    private QuoteModel $qMod;
    private CharacterModel $caMod;
    private SourceModel $srcMod;
    private QuestionModel $questMod;
    private ImageModel $iMod;
    private QuizModel $quizModel;


    public function __construct() {
        global $co;
        $this->cMod = new CommentaryModel(new CommentaryGateway($co));
        $this->uMod = new UserModel(new UserGateway($co));
        $this->qMod = new QuoteModel(new QuoteGateway($co));
        $this -> questMod = new QuestionModel(new QuestionGateway($co));
        $this -> caMod = new CharacterModel(new CharacterGateway($co));
        $this->srcMod = new SourceModel(new SourceGateway($co));
        $this->iMod = new ImageModel(new ImageGateway($co));
        $this->quizModel = new QuizModel(new QuizGateway($co));
    }

    public function accueilQuiz() {
        global $vues;
        $quizs = $this->quizModel->listQuiz();
        require_once $vues['accueilQuiz'];
    }

    public function randomQuiz() {
        global $vues;

        $canswer = Verification::verifChar($_POST['canswer'] ?? null);

        /*---------------------------------------------*/

        if(!isset($_SESSION["no_question"])){
            $no_question = 0;
        }
        else{
            $no_question = Verification::verifChar($_SESSION["no_question"]);

            if($canswer!=null){
                $no_question=$no_question+1;
            }
            
            if($no_question < 1 ){
                $no_question = 0;
            }
        }
        $_SESSION["no_question"]=$no_question;

        /*---------------------------------------------*/

        if(!isset($_SESSION["nbVie"])){
            $vie = 3;
        }
        else{
            $vie = Verification::verifChar($_SESSION["nbVie"]) ;
            if($vie > 3 ){
                $vie = 3;
            }
            elseif($vie < 1){
                $vie = 0;
            }
        }

        /*---------------------------------------------*/

        $answera = Verification::verifChar($_POST['answera'] ?? null);
        $answerb = Verification::verifChar($_POST['answerb'] ?? null);
        $answerc = Verification::verifChar($_POST['answerc'] ?? null);
        $answerd = Verification::verifChar($_POST['answerd'] ?? null);


        $answer = null;

        if ($answera) {
            $answer = $answera;
        } elseif ($answerb) {
            $answer = $answerb;
        } elseif ($answerc) {
            $answer = $answerc;
        } elseif ($answerd) {
            $answer = $answerd;
        }
        if($answer != $canswer){
            $vie=$vie-1;
        }

        /*---------------------------------------------*/

        $_SESSION["nbVie"]=$vie;

        if($vie<=0){
            $score=($no_question - 3);
            $next=false;
            $nbQuestion=$no_question;

            unset($_SESSION["no_question"]);
            unset($_SESSION["nbVie"]);

            require_once $vues['endQuizRandom'];
        }
        else{
            /*---------------------------------------------*/
    
            $question = $this->questMod->QuestionForQuoteToCarac('fr');
    
            require_once $vues['quizRandom'];
        }
    }
    
    public function profil() {

        global $vues;
        $p = $this->uMod->getUsername($_SESSION["user"]);
        $listImg = $this->iMod->getAllImg() ;

        // Pour les messages d'erreur
        $error_message = null;
        if (isset($_SESSION['error_message'])) {
            $error_message = $_SESSION['error_message'];
            // Supprimer le message d'erreur après l'avoir lu
            unset($_SESSION['error_message']);
        }
        require_once $vues['profil'];

    }


    public function addComment(){
        global $racine;
        $id = $_POST['idQuote'];
        $this->cMod->createComment(Verification::verifChar($_POST['content']),
                                    Verification::verifChar($_POST['idQuote']),
                                    $this->uMod->getIdByUsername(Verification::verifChar($_SESSION['user'])));
        header("Location:".$racine."/quote/$id");
    }
    

    public function favorite(array $args) {
        global $vues;
        
        $userId = $this->uMod->getIdByUsername($_SESSION["user"]);

        $favorites = $this->qMod->getFavorites($userId);

        require_once $vues['favorite'];
    }

    public function unlog(){
        global $racine;
        session_unset();
        session_destroy();
        $_SESSION = array();
        header("Location:".$racine);
    }

    public function quiz(array $args){
        global $vues;
        $id=$args['id'];
        $nb_questions = $this->getNumberOfQuestion($id);

        $action = $_REQUEST['action'] ?? null;
        switch ($action) {
            case 'canswer':
                if ($this->CorrectAnswer())
                    $_SESSION['score'] = Verification::verifChar( isset( $_SESSION['score']) ? ($_SESSION['score'] + 1) : 1 ) ;
                $this->continueQuiz($id, $nb_questions);
                break;
            default:
                switch($id)
                {
                    case null:
                        // page erreur
                        break;
                    default:
                        $_SESSION['score'] = Verification::verifChar($_SESSION['score'] ?? 0);
                        $this->showQuestion($id, Verification::verifChar($_SESSION['no_question'] ?? 0));
                        break;
                }
        }
    }

    /**
     * @throws SyntaxError
     * @throws RuntimeError
     * @throws LoaderError
     */
    public function continueQuiz(int $id_quiz, int $total_questions) : void{
        global $racine;
        $score = $_SESSION['score'];
        $_SESSION['no_question'] = Verification::verifChar( isset($_SESSION['no_question']) ? ($_SESSION['no_question'] + 1) : 1);
        if ($_SESSION['no_question'] >= $total_questions) {
            $_SESSION['no_question'] = 0;
            $this->endQuiz($id_quiz, $score);
            $_SESSION['score'] = 0;
        }
        else header("Location: ".$racine."/quiz/$id_quiz"); ///~kekentin/WF/WF-Website

    }

    /**
     * @throws SyntaxError
     * @throws RuntimeError
     * @throws LoaderError
     */
    public function endQuiz(int $id_quiz, int $score) : void{
        global $vues,$co;

        $gw = new QuizGateway($co);
        $mdl = new QuizModel($gw);
        $nbQuestion = $this->getNumberOfQuestion($id_quiz);
        if ($mdl->getQuiz($id_quiz + 1)){
            $next = true;
            require_once $vues['endQuiz'];
        }
        $next = false;
        require_once $vues['endQuiz'];
    }

    public function CorrectAnswer() : bool{
        $answera = Verification::verifChar($_POST['answera'] ?? null);
        $answerb = Verification::verifChar($_POST['answerb'] ?? null);
        $answerc = Verification::verifChar($_POST['answerc'] ?? null);
        $answerd = Verification::verifChar($_POST['answerd'] ?? null);

        $id= null;
        $answer = null;

        if ($answera) {
            $answer = explode('-', $answera)[0];
            $id = (int) explode('-', $answera)[1];
        } elseif ($answerb) {
            $answer = explode('-', $answerb)[0];
            $id = (int) explode('-', $answerb)[1];
        } elseif ($answerc) {
            $answer = explode('-', $answerc)[0];
            $id = (int) explode('-', $answerc)[1];
        } elseif ($answerd) {
            $answer = explode('-', $answerd)[0];
            $id = (int) explode('-', $answerd)[1];
        }
        $res = $this->questMod->getQuestion($id);
        return $answer == $res->getCanswer();
    }

    public function GetQuestion(int $id): array{
        global $co;
        $gw = new QuizQuestionGateway($co);
        $mdl = new QuizQuestionModel($gw);
        return $mdl->getAllQuestionByQuiz($id, $co);
    }

    /**
     * @throws RuntimeError
     * @throws SyntaxError
     * @throws LoaderError
     */
    public function showQuestion(int $id, int $num) : void{
        global $vues,$twig;
        $q = $this->GetQuestion($id);
        $question = $q[$num] ?? $q[0];
        $idquestion = $question->getIdQuestion();
        $nbQuestion = $this->getNumberOfQuestion($id);
        require_once $vues['quiz'];

        //echo $twig->render('quiz.html.twig', ['question' => $question,'id'=>$idquestion]);
    }

    public function getQuiz(int $id) : QuizModel
    {
        global $co;
        $gw = new QuizGateway($co);
        $mdl = new QuizModel($gw);
        return $mdl->getQuiz($id);
    }


    public function getNumberOfQuestion(int $id) : int{
        global $co;
        $gw = new QuizGateway($co);
        $mdl = new QuizModel($gw);
        return $mdl->getQuiz($id)->getNbQuestions();
    }

    public function addFav(array $arg){
        global $racine;
        $id= $arg['id'] ?? 1;
        $this->uMod->addFavorite(Verification::verifChar($_SESSION["user"]),$id);
        header("Location:" . $racine . "/quote/$id");
        
    }

    public function supFav(array $arg){
        global $racine;
        $id= $arg['id'] ?? 1;
        $this->uMod->supFavorite(Verification::verifChar($_SESSION["user"]),$id);
        header("Location:". $racine ."/quote/$id");
    }



    // ===================== UPDATE DATA USER FUNCTION =====================
    public function changedata() : void{
        global $vues, $racine;
        if ($_POST)
        {
            $newImage = $_POST['image'] ?? null;
            $newPseudo = $_POST['pseudo'] ?? null;
            $newEmail = $_POST['email'] ?? null;
            $oldPasswd = $_POST['oldPasswd']?? null;
            $newMdpFirst = $_POST['passwdFirst'] ?? null;
            $newMdpSecond = $_POST['passwdSecond'] ?? null;

            
            if($newPseudo){//Modif le pseudo
                $this->updatePseudo($newPseudo);
            }
            else if($newEmail){//Modif l'email
                $this->updateEmail($newEmail);
                $this->sendEmailChangeLogin($newEmail); //Envoie un email confirmant le changement d'email
            }
            else if($newMdpFirst && $newMdpSecond){ //Modif le mot de passe
                $this->updatePassWd($oldPasswd, $newMdpFirst,$newMdpSecond);
            }
            else if($newImage){//Modif l'image
                $this->updateImg($newImage);
            }
        }
        header("Location: ". $racine."/profil");
       
    }


    public function updatePseudo(string $newPseudo){
        $user = $this-> uMod->setUsername($_SESSION['user'], $newPseudo);

        if($user == $newPseudo){
            $_SESSION['user'] = $newPseudo;
            
        }
        else{ // pseudo invalide
            $_SESSION['error_message'] = $newPseudo . " n'est pas valide ou non libre";
            header("Location: ". $racine."/profil");
        }
    }


    public function updateEmail(string $newEmail){
        $user = $this-> uMod->setEmail($_SESSION['user'], $newEmail);

        if($user == $_SESSION['user']){ // si email incorrect, renvoie le nom de l'utilisateur de la session
            $_SESSION['error_message'] = "L'email n'est pas valide";
            header("Location: ". $racine."/profil");
        }
    }


    public function updatePassWd(string $oldPasswd, string $newMdpFirst, string $newMdpSecond){
        if(!$oldPasswd){
            $_SESSION['error_message'] = "Veuillez taper votre ancien mot de passe";
            header("Location: ". $racine."/profil");
        }

        else if(!$this->uMod->isPassWd($_SESSION['user'], $oldPasswd)){
            $_SESSION['error_message'] = "Votre ancien mot de passe est incorrect";
            header("Location: ". $racine."/profil");
        }

        else{
            if($newMdpFirst == $newMdpSecond){
            
                $option = ['cost' => 12];
                $newPassWd = password_hash($newMdpFirst, PASSWORD_BCRYPT, $option);
                $user = $this-> uMod->setPassWd($_SESSION['user'], $newPassWd);
            }
            else{
                $_SESSION['error_message'] = "Les mots de passe ne correspondent pas";
                header("Location: ". $racine."/profil");
            }
        }
    }

    public function updateImg(string $newImage){
        $user = $this->uMod->setImage($_SESSION['user'],$newImage);
    }





    // ===================== SUBMIT FUNCTION =====================

    /**
     * @throws SyntaxError
     * @throws RuntimeError
     * @throws LoaderError
     */
    public function submit() : void{
        global $vues;
        $p = $this->caMod->getAllPerso();
        $s = $this->srcMod->getAllSources();
        require_once $vues['submitQuote'];
    }

    /**
     * @throws SyntaxError
     * @throws RuntimeError
     * @throws LoaderError
     */

    public function toSubmit(string $content,string $character, string $source)
    {
        global $co;
        if ($_POST)
        {
            $errors = [null, null];

            $nameSrc = $this->srcMod->getSourceById($source)->getTitle();
            $nameChar = $this->caMod->getCharacterById($character)->getName();

            if (!$character)
                $errors[0] = "Personnage inexistant";
            if (!$source)
                $errors[1] = "Source inexistante";
            $this -> qMod -> addQuote($content,'fr',$character,$source,$this->uMod->getIdByUsername(Verification::VerifChar($_SESSION['user'])));
            $this -> recapSubmitQuote(array('content' => $content, 'src' => $nameSrc, 'character' => $nameChar));
        }
    }

    /**
     * @throws SyntaxError
     * @throws RuntimeError
     * @throws LoaderError
     */
    public function validsubmit() : void
    {
        if($_POST['src'] == 'other' && $_POST['character'] == 'other'){
            global $vues;
            $src = true;
            $char = true;
            $srcId = null;
            $charId = null;
            require_once $vues['create'];
            exit();
        }
        elseif($_POST['src'] == 'other'){
            global $vues;
            $src = true;
            $char = false;
            $srcId = null;
            $charId = $_POST['character'];
            require_once $vues['create'];
            exit();
        }
        elseif($_POST['character'] == 'other'){
            global $vues;
            $src = false;
            $char = true;
            $srcId = $_POST['src'];
            $charId = null;
            require_once $vues['create'];
            exit();
        }
        $recap = $this -> toSubmit($_POST['content'],$_POST['character'],$_POST['src']);
    }

    public function recapSubmitQuote(array $recap){
        global $vues;
        require_once($vues["recap"]);
    }


    
    // ===================== SUBMIT QUOTE FUNCTION =====================

    public function getIdOfUser() : ?int
    {
        if (isset($_SESSION['user']))
        {
            global $co;
            $gw = new UserGateway($co);
            $mdl = new UserModel($gw);

            return $mdl -> getUsername($_SESSION['user']) -> getId();
        }
        return null;
    }


    public function add(){
        global $vues, $repImg;
        $error = [];
        $src = false;
        $char = false;
        var_dump($_FILES);
        if($_POST['req'] == "both"){
            $src = true;
            $char = true;
        }

        if($_POST['req'] == "src" or $src == true){
            $type = array("movie","serie","video-game","anime");
            if(Verification::verifNotNull($_POST["titre"])){
                $_POST["titre"] = Verification::verifChar($_POST["titre"]);
                if($this->srcMod->existSource($_POST["titre"],$_POST["type"])){
                    $error[] = "La source existe déja";
                }
            }
            else{
                $error[] = "Le titre doit être définit";
            }
            if(Verification::verifNotNull($_POST["date"])){
                $_POST["date"] = Verification::verifChar($_POST["date"]);
                if(intval($_POST["date"],10) < 1850 or intval($_POST["date"],10) > date( "Y", time() )){
                    $error[] = "La date est invalide";
                }
            }
            else{
                $error[] = "La date doit être définit";
            }
            if(Verification::verifNotNull($_POST["type"])){
                $_POST["type"] = Verification::verifChar($_POST["type"]);
                if(!in_array($_POST["type"],$type)){
                    $error[] = "Le type indiquer est inexistant";
                }
            }
            else{
                $error[] = "Le type doit être définit";
            }
        }

        if($_POST['req'] == "char" or $char == true){
            if(Verification::verifNotNull($_POST["name"])){
                $_POST["name"] = Verification::verifChar($_POST["name"]);
            }
            else{
                $error[] = "Le nom doit être définit";
            }
            
            // upload de la photo
            if (isset($_FILES['avatar'])) {

                $tabExtension = explode('.', $_FILES['avatar']['name']);
                $extension = strtolower(end($tabExtension));
                $extensions = ['jpg', 'png', 'jpeg'];
                if(in_array($extension, $extensions)){
                    move_uploaded_file($_FILES['avatar']['tmp_name'], $repImg.$_FILES['avatar']['name']);
                    $filePath = $repImg.$_FILES['avatar']['name'];
                }
                else{
                    $error[] =  "Mauvaise extension";
                    exit();
                }
            }
            else{
                $error[] = "Aucune photo";
            }
        
        }

        if($error == []){
            $recap['content'] = $_POST['content'];
            if($_POST['req'] == "both"){
                $this->srcMod->createSource($_POST["titre"], $_POST["date"], TypeSourceEnum::from($_POST["type"]));
                $idImg = $this->iMod->createImgModelWithoutId($filePath);
                $this->caMod->createCharacterWithoutId($_POST["name"], $idImg);
                $idC = $this-> caMod -> getCharacterByName($_POST["name"])->getIdCharacter();
                $idS = $this -> srcMod -> getSourceByTitle($_POST["titre"])->getIdSource();
            }
            elseif($_POST['req'] == "src"){
                $this->srcMod->createSource($_POST["titre"], $_POST["date"], TypeSourceEnum::from($_POST["type"]));
                $idC = Verification::VerifChar($_POST["character"]);
                $idS = $this -> srcMod -> getSourceByTitle($_POST["titre"])->getIdSource();
            }
            elseif($_POST['req'] == "char"){
                $idImg = $this->iMod->createImgModelWithoutId($filePath);
                $this->caMod->createCharacterWithoutId($_POST["name"], $idImg);
                $idC = $this-> caMod -> getCharacterByName($_POST["name"])->getIdCharacter();
                $idS = Verification::VerifChar($_POST["src"]);
            }
            $this -> toSubmit(Verification::VerifChar($_POST["content"]),$idC,$idS);
        }
        else{
            require_once($vues["create"]);
        }
    }

    public function questionSuivantAleatoire(){

    }


    // ===================== DELETE ACCOUNT FUNCTION =====================

    public function deleteAccount(){
        $this->uMod->deleteAllCommentary($_SESSION["user"]); // Delete all commentary
        $this->uMod->deleteAllFavorite($_SESSION["user"]); // Delete all favorite
        $this->uMod->deleteAccount($_SESSION["user"]);
        $this->unlog();
    }


    // ===================== EMAIL FUNCTION =====================

    public function sendEmailChangeLogin(string $email) {
        // Génère les données du message
        $sujet = "What The Fantasy - Changement d'Email";
        $urlImage = "public/images/Baneer.png";


        // Génère une frontière unique pour l'email
        $boundary = "-----=" . md5(uniqid(mt_rand()));
    
        //Instancie les headers
            $headers = "From: noreply@whatTheFantasy.com\r\n";
            $headers .= "MIME-Version: 1.0\r\n";
            $headers .= "Content-Type: multipart/related; boundary=\"$boundary\"\r\n";
        
    
        // Corps de l'email HTML avec l'image intégrée
        $corpsMessage = "--$boundary\r\n";
        $corpsMessage .= "Content-Type: text/html; charset=UTF-8\r\n";
        $corpsMessage .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
    
        // Ajoute le message HTML
        $corpsMessage .= "<html>
        <body>
            <img src=\"cid:image1\" alt=\"Image\" style=\"width: 1200px; height: auto;\" />
            <p>Bonjour,</p>
    
            <p>Vous venez de changer votre adresse mail. Dorénavant, votre email sera $email.</p>
            <p>L'équipe du site</p>
        </body>
    </html>\r\n";
    
        // Ajoute l'image en pièce jointe
        $corpsMessage .= "--$boundary\r\n";
        $corpsMessage .= "Content-Type: image/jpeg; name=\"image.jpg\"\r\n";
        $corpsMessage .= "Content-Transfer-Encoding: base64\r\n";
        $corpsMessage .= "Content-ID: <image1>\r\n\r\n";
    
        
        $imageContent = file_get_contents($urlImage);// Lecture et encodage de l'image en base64
        if ($imageContent === false) {
            return "Impossible de charger l'image spécifiée.";
        }
        $corpsMessage .= chunk_split(base64_encode($imageContent)) . "\r\n";
    
        
        $corpsMessage .= "--$boundary--";// Fin du corps de l'email
    
        
        mail($email, $sujet, $corpsMessage, $headers);// Envoi de l'email
    }
}
