import { Router, Request, Response, NextFunction } from "express";
import { titreBase } from "../utils/define";
import { errorCode500 } from "../utils/errors";
import { coursController, questionControleur, questionnaireControleur } from "../locator";
import { Cours } from "../classes/cours";
import { Questionnaire } from "../classes/questionnaire";
import { Enseignant } from "../classes/enseignant";
import { authenticate } from "../middlewares/authenticate";
import { authorizeEnseignant } from "../middlewares/authorizeEnseignant";

export class QuestionnaireRouter {
  private _router: Router;

  get router() {
    return this._router;
  }

  constructor() {
    this._router = Router();
    this.init();
  }

  public async questionnaires(req: Request, res: Response, next: NextFunction) {
    try {
      const code = req.params.code;
      const user = req.body.user as Enseignant;

      const questionnaireMap: Map<string, Questionnaire> =
      questionnaireControleur.recupererQuestionnaires();
      let questionnaireArr = [];

      questionnaireMap.forEach((val, key) => {
        if (val._cours === code
            && val._enseignant === user.id) {
          questionnaireArr.push({
            nom: key,
            cours: val._cours,
            user: val._enseignant
          });
        }
      });

      res.render("questionnaire/questionnaires", {
        title: `${titreBase}`,
        user: user,
        code: code,
        questionnaires: questionnaireArr
      });
    } catch (error) {
      errorCode500(error, req, res);
    }
  }

  public async visualiserCoursActifs(
    req: Request,
    res: Response,
    next: NextFunction
  ) {
    try {
      const user = req.body.user as Enseignant;
      const code = req.params.code;

      const coursRecuperes: Cours[] = coursController.recupererCours(user) as Cours[];
      let coursActifs = [];

      coursRecuperes.forEach(cours => {
        const nbQuestionnaires = questionnaireControleur.getNbQuestionnairesParCours(
          cours.group_id.split('-')[1]
        );

        if(cours.getEnseignantId() === user.id && cours.actif)
          coursActifs.push({
            nom: cours.group_id.split('-')[1],
            nbQuestionnaires: nbQuestionnaires
          });
      });

      res.render("questionnaire/coursActifsQuestionnaires", {
        title: `${titreBase}`,
        user: user,
        code: code,
        coursActifs: coursActifs
      });
    } catch (error) {
      errorCode500(error, req, res);
    }
  }

  public async formulerQuestionnaire(
    req: Request,
    res: Response,
    next: NextFunction
  ) {
    try {
      const user = req.body.user as Enseignant;

      const code = req.params.code;

      res.render("questionnaire/formuler-questionnaire", {
        title: `${titreBase}`,
        user: user,
        code: code,
      });
    } catch (error) {
      errorCode500(error, req, res);
    }
  }

  public async reformulerQuestionnaire(
    req: Request,
    res: Response,
    next: NextFunction
  ) {
    try {
      const nom = req.params.nom
      const code = req.params.code

      const questionnaire = questionnaireControleur.recupererQuestionnaire(nom)

      const toutQuestions = Array.from(questionControleur.recupererQuestions().values())
      
      res.render("questionnaire/reformuler-questionnaire", {
        title: `${titreBase}`,
        questionnaire: questionnaire,
        toutQuestions: toutQuestions,
        user: req.body.user,
        code: code
      });
    } catch (error) {
      errorCode500(error, req, res);
    }
  }

  public async ajouterQuestionnaire(req: Request, res: Response, next: NextFunction) {
    const user = req.body.user as Enseignant;

    const {
      cours,
      nom,
      description,
      etat
    } = req.body;

    console.log("créer questionnaire");
    console.log(req.body);

    try {
      questionnaireControleur.ajouterQuestionnaire(
        user ? user.id : "error",
        cours,
        nom,
        description,
        etat
      );

      req.flash("info", `Nouveau questionnaire : ${nom}`);
      res.redirect(`/questionnaires/questions/categories/${nom}`);
    }
    catch (error) {
      console.log(error.message);
      if (error.message.includes("existe déjà")) {
        req.flash("error", `Un questionnaire avec le nom "${nom}" existe déjà`);
        res.redirect(`/questionnaires/formuler/${cours}`);
      }
      else if(error.message.includes("ne peut pas etre vide")) {
        req.flash("error", `Le nom du questionnaire ne peut pas être vide`);
        res.redirect(`/questionnaires/formuler/${cours}`);
      }
      else {
        errorCode500(error, req, res);
      }
    }
  }
  

  public async supprimerQuestionnaire(req: Request, res: Response, next: NextFunction) {
    const user = req.body.user as Enseignant;

    const nom = req.params.nom;
    const cours = questionnaireControleur.recupererQuestionnaire(req.params.nom)._cours;

    console.log("supprimer question");
    console.log(req.body);

    try {
      questionnaireControleur.supprimerQuestionnaire(user.id, cours, nom);
      req.flash("info", `Supprimer Questionnaire: ${nom}`);
      res.redirect(`/questionnaires/${cours}`);
    } catch (error) {
      errorCode500(error, req, res);
    }
  }

  public async modifierQuestionnaire(req: Request, res: Response, next: NextFunction) {
    const user = req.body.user as Enseignant;

    const {
      cours,
      nom,
      description,
      etat,
      questionAssocier,
      questionDissocier,
      ordreQuestion
    } = req.body;

    console.log(req.body);

    try {
      questionnaireControleur.modifierQuestionnaire(
        user ? user.id : "error",
        cours,
        nom,
        description,
        etat === 'on',
        questionAssocier === "Associer une question" ? null : questionAssocier,
        questionDissocier === "Dissocier une question" ? null : questionDissocier,
        ordreQuestion.split(",")
      );

      req.flash("info", `Le questionnaire ${nom} a été modifié`);
      res.redirect(`/questionnaires/questions/categories/${nom}`);
    }
    catch (error) {
      console.log(error.message);
      if (error.message.includes("existe déjà")) {
        req.flash("error", `Un questionnaire avec le nom "${nom}" existe déjà`);
        res.redirect(`/questionnaires/formuler/${cours}`);
      }
      else if(error.message.includes("ne peut pas etre vide")) {
        req.flash("error", `Le nom du questionnaire ne peut pas être vide`);
        res.redirect(`/questionnaires/formuler/${cours}`);
      }
      else {
        errorCode500(error, req, res);
      }
    }
  }

  public async ajouterQuestion(req: Request, res: Response, next: NextFunction) {
    const user = req.body.user as Enseignant;

    const nomQuestionnaire = req.params.nom;
    const questionsChoisies = req.body.questionsChoisies;

    console.log("ajouter question au questionnaire");
    console.log(req.body);

    try {
      const questionnaire = questionnaireControleur.recupererQuestionnaire(nomQuestionnaire);
      
      if(questionsChoisies instanceof Array) {
        questionsChoisies.forEach((nomQuestion) => {
          const question = questionControleur.recupererQuestion(nomQuestion, user.id);
          
          questionnaire.ajouterQuestion(question);
    
          req.flash("info", `Question ${nomQuestion} ajoutée au questionnaire ${nomQuestionnaire}`);
        });
      }
      else {
        const question = questionControleur.recupererQuestion(questionsChoisies, user.id);
        questionnaire.ajouterQuestion(question);
        req.flash("info", `Question ${questionsChoisies} ajoutée au questionnaire ${nomQuestionnaire}`);
      }

      res.redirect(`/questionnaires/questions/categories/${nomQuestionnaire}`);
    }
    catch (error) {
      errorCode500(error, req, res);
    }
  }

  public async visualiserCategoriesParQuestion(req: Request, res: Response, next: NextFunction) {
    const user = req.body.user as Enseignant;

    try {
      const nomFormulaire = req.params.nom;

      let categorieSet = new Set();
      let categorieArr = [];
      const questions = questionControleur.recupererQuestions();

      questions.forEach((val) => {
        if(val.getEnseignant() === user.id) {
          let categorie = val.getCategorie();

          if(!categorieSet.has(categorie))
            categorieArr.push(categorie);

          categorieSet.add(categorie);
        }
      });

      res.render("questionnaire/categoriesParQuestion", {
        title: `${titreBase}`,
        user: user,
        nomFormulaire: nomFormulaire,
        categories: categorieArr
      });
    }
    catch (error) {
      errorCode500(error, req, res);
    }
  }

  public async visualiserQuestionsDansCategorie(req: Request, res: Response, next: NextFunction) {
    const user = req.body.user as Enseignant;

    try {
      const nomFormulaire = req.params.nom;
      const categorie = req.params.categorie;

      let questionsDansCategorie = [];
      const questions = questionControleur.recupererQuestions();
      const questionnaire = questionnaireControleur.recupererQuestionnaire(nomFormulaire);

      questions.forEach((val) => {
        if(val.getEnseignant() === user.id
          && val.getCategorie() === categorie) {
          const nom = val.getNom();
          let questionnaireCounter = 0;

          questionnaireControleur.recupererQuestionnaires().forEach((questionnaire, key) => {
            if(questionnaire._questions.includes(val))
              questionnaireCounter++;
          })

          questionsDansCategorie.push({nom: nom, questionnaireCounter: questionnaireCounter});
        }
      });

      res.render("questionnaire/questionsDansCategorie", {
        title: `${titreBase}`,
        user: user,
        nomFormulaire: nomFormulaire,
        categorie: categorie,
        questions: questionsDansCategorie
      });
    }
    catch (error) {
      errorCode500(error, req, res);
    }
  }

  public async visualiserDetails(req: Request, res: Response, next: NextFunction) {
    const user = req.body.user as Enseignant;

    try {
      const nomQuestionnaire = req.params.nom;
      const questionnaire = questionnaireControleur.recupererQuestionnaire(nomQuestionnaire);
      const questions = questionnaire._questions;
      const notes = questionnaire.genererNotes();

      console.log(questions)
      console.log(questionnaire)
      
      res.render("questionnaire/detailsQuestionnaire", {
        title: `${titreBase}`,
        user: user,
        questionnaire: questionnaire,
        questions: questions,
        notes: notes
      });
    }
    catch (error) {
      errorCode500(error, req, res);
    }
  }

  private init() {
    this._router.post("/nouveau", authenticate, this.ajouterQuestionnaire.bind(this));
    this._router.post("/ajouter/:nom", authenticate, this.ajouterQuestion.bind(this));
    this._router.get("/cours-actifs", authenticate, this.visualiserCoursActifs.bind(this));
    this._router.get("/:code", authenticate, authorizeEnseignant, this.questionnaires.bind(this));
    this._router.get("/formuler/:code", authenticate, this.formulerQuestionnaire.bind(this));
    this._router.get("/reformuler-questionnaire/:nom", authenticate, this.reformulerQuestionnaire.bind(this));
    this._router.post("/modifier-questionnaire", authenticate, this.modifierQuestionnaire.bind(this));
    this._router.get("/questions/categories/:nom", authenticate, this.visualiserCategoriesParQuestion.bind(this));
    this._router.get("/:nom/questions/:categorie", authenticate, this.visualiserQuestionsDansCategorie.bind(this));
    this._router.get("/details/:nom", authenticate, this.visualiserDetails.bind(this));
    this._router.post("/supprimer-questionnaire/:nom", authenticate, this.supprimerQuestionnaire.bind(this));
  }
}

export const questionnaireRouter = new QuestionnaireRouter();
