const { Op, QueryTypes  } = require("sequelize");

const config = require("../config/main.js");
const configQuestionnaires = require("../config/questionnaires.js");

const tool = require("../tools/main");
const toolError = require("../tools/error");
const toolFile = require("../tools/file");

const questionnaireCtrl = require("./questionnaire");

const txt = require("../lang/"+config.adminLang+"/question");
const txtGeneral = require("../lang/"+config.adminLang+"/general");

exports.create = async (req, res, next) =>
{
    try
    {
        const db = require("../models/index");
        const questionnaire=await questionnaireCtrl.searchQuestionnaireById(req.body.QuestionnaireId);
        if(!questionnaire)
            throw txt.needQuestionnaire;
        else if(config.nbQuestionsMax !== 0 && questionnaire.Questions.length >= config.nbQuestionsMax)
            res.status(400).json({ errors: [txt.needMaxQuestions+config.nbQuestionsMax] });
        else
        {
            const question=await db["Question"].create({ ...req.body }, { fields: ["text", "explanation", "rank", "QuestionnaireId"] });
            await questionnaireCtrl.creaQuestionnaireJson(req.body.QuestionnaireId);
            req.body.QuestionId=question.id;
            next();// je passe la main au contrôleur qui gère les réponses possibles saisies pour cette question
            return true;
        }
        next();
    }
    catch(e)
    {
        const returnAPI=toolError.returnSequelize(e);
        if(returnAPI.messages)
        {
            res.status(returnAPI.status).json({ errors : returnAPI.messages });
            next();
        }
        else
            next(e);
    }
}

exports.modify = async (req, res, next) =>
{
    try
    {
        const db = require("../models/index");
        const question=await searchQuestionById(req.params.id);
        if(!question)
            throw txt.notFound;
        const questionnaire=questionnaireCtrl.searchQuestionnaireById(question.Question.QuestionnaireId);
        if(!questionnaire)
            throw txt.needQuestionnaire;
        if(req.connectedUser.User.status==="creator" && req.connectedUser.User.id!==questionnaire.CreatorId)
            res.status(401).json({ errors: txtGeneral.notAllowed });
        else
        {
            await db["Question"].update({ ...req.body }, { where: { id : req.params.id } , fields: ["text", "explanation", "rank"], limit:1 });
            next();// je passe la main au contrôleur qui gère les réponses possibles saisies pour cette question
            return true;
        }
    }
    catch(e)
    {
        const returnAPI=toolError.returnSequelize(e);
        if(returnAPI.messages)
        {
            res.status(returnAPI.status).json({ errors : returnAPI.messages });
            next();
        }
        else
            next(e);
    }
}

exports.delete = async (req, res, next) =>
{
    try
    {
        const question=await searchQuestionById(req.params.id);
        if(!question)
            throw txt.notFound;
        let questionnaire=questionnaireCtrl.searchQuestionnaireById(question.Question.QuestionnaireId);
        if(!questionnaire)
            throw txt.needQuestionnaire;
        if(req.connectedUser.User.status==="creator" && req.connectedUser.User.id!==questionnaire.CreatorId)
            res.status(401).json({ errors: txtGeneral.notAllowed });
        else
        {
            if(await deleteQuestionById(req.params.id))
            {
                questionnaire=await questionnaireCtrl.searchQuestionnaireById(req.body.QuestionnaireId,true);// nécessaire réaffichage après suppression
                res.status(200).json({ message: txt.deleteOkMessage, questionnaire: questionnaire });
            }
            else
                res.status(400).json({ errors: txtGeneral.serverError });
        }
        next();// pour middleware mesurant la durée de la réponse
    }
    catch(e)
    {
        next(e);
    }       
}

// CRON supprimant les fichiers Json obsolètes
exports.deleteJsonFiles= async (req, res, next) =>
{
    try
    {
        const db = require("../models/index");
        const questions=await db["Question"].findAll({ attributes: ["id"] });
        let saveFiles=[];
        for(let i in questions)
            saveFiles.push(questions[i].id+".json");
        const deleteFiles = await toolFile.deleteFilesInDirectory(configQuestionnaires.dirCacheQuestions, saveFiles);
        res.status(200).json(deleteFiles);
        next();
    }
    catch(e)
    { 
        next(e);
    }
}

// FONCTIONS UTILITAIRES

// Création du fichier des données relatives à une question (avec les réponses proposées)
const creaQuestionJson = async (id) =>
{
    const db = require("../models/index");
    const Question=await db["Question"].findByPk(id);
    if(Question)
    {
        let datas={ Question };
        const Choices=await db["Choice"].findAll({ where: { QuestionId: Question.id }});
        if(Choices)
            datas.Choices=Choices;
        await toolFile.createJSON(config.dirCacheQuestions, id, datas);
        return datas;
    }
    else
        return false;
}
exports.creaQuestionJson = creaQuestionJson;

// Retourne les données d'une question
const searchQuestionById = async (id) =>
{
    const question=await toolFile.readJSON(config.dirCacheQuestions, id);
    if(question)
        return question;
    else
        return await creaQuestionJson(id);
}
exports.searchQuestionById = searchQuestionById;

// Supprime une question et ses dépendances
const deleteQuestionById = async (id) =>
{
    const db = require("../models/index");
    const question=await searchQuestionById(id);
    if(!question)
        throw txt.notFound;
    const nb=await db["Question"].destroy( { where: { id : id }, limit:1 });
    if(nb===1)
    {
        toolFile.deleteJSON(config.dirCacheQuestions, id);
        questionnaireCtrl.creaQuestionnaireJson(question.Question.QuestionnaireId);
        return true;
    }
    else
        throw txt.notFound;
}
exports.deleteQuestionById = deleteQuestionById;