import "jest-extended";
import { Question } from "../../src/classes/question";
import { Questionnaire } from "../../src/classes/questionnaire";
import { QuestionnaireControleur } from "../../src/controleurs/questionnaireControleur";
import { initControllers, questionControleur, questionnaireControleur } from "../../src/locator";
import supertest from 'supertest';
import app from '../../src/app';
import { QuestionControleur } from "../../src/controleurs/questionControleur";

// Questionnaire
const enseignant = "ENSEIGNANT TEST";
const cours = "LOGTEST-01";
const autrCours = "LOGTEST-02";
const nom = "QUESTIONNAIRE NOM TEST";
const description = "DESCRIPTION TEST";
const etat = true;
const questions = [];

// Questions
const qcours = "LOGTEST-01";
const qcategorie = "cat1";
const qnom = "QUESTION NOM TEST";
const qenonce = "ENONCE TEST";
const qreponse = true;
const qretroactionPositive = "RETRO POSITIVE TEST";
const qretroactionNegative = "RETRO NEGATIVE TEST";

const request = supertest(app);

describe('CU05a postconditions test', () => {
    let questionnaire: Questionnaire;
    let qCtrl: QuestionnaireControleur;

    beforeEach(async() =>  {
        qCtrl = new QuestionnaireControleur();
        qCtrl.ajouterQuestionnaire(enseignant, cours, nom, description, etat);
        questionnaire = qCtrl.recupererQuestionnaire(nom) as Questionnaire;
    });

    it('Nouveau questionnaire associé au cours',async () => {
        expect(qCtrl.recupererQuestionnaire(nom)?._nom).toBe(nom);
        expect(qCtrl.recupererQuestionnaire(nom)?._cours).toBe(cours);
    });

    it('Nouveau questionnaire pas associé à un autre cours',async () => {
        expect(qCtrl.recupererQuestionnaire(nom)?._cours).not.toBe(autrCours);
    });

    it('Questionnaire associé à 0 question',async () => {
        expect(qCtrl.recupererQuestionnaire(nom)?._questions.length).toBe(0);
    });

    it('Questionnaire associé à plusieurs (2) questions',async () => {
        const question1 = new Question(
            qcours,
            qcategorie,
            qnom,
            qenonce,
            qreponse,
            qretroactionPositive,
            qretroactionNegative,
            enseignant
        );

        const question2 = new Question(
            qcours,
            qcategorie,
            qnom + "2",
            qenonce,
            qreponse,
            qretroactionPositive,
            qretroactionNegative,
            enseignant
        );

        questionnaire?.ajouterQuestion(question1);
        questionnaire?.ajouterQuestion(question2);

        expect(questionnaire?._questions.length).toBe(2);
    });

    it('Nouveau questionnaire associé au cours',async () => {
        expect(qCtrl.recupererQuestionnaire(nom)?._nom).toBe(nom);
        expect(qCtrl.recupererQuestionnaire(nom)?._cours).toBe(cours);
    });

    it('Impossible d\'ajouter un questionnaire avec un nom existant',async () => {
        expect(() => qCtrl.ajouterQuestionnaire(enseignant, cours, nom, description, etat))
            .toThrow(new Error(`Le questionnaire ${nom} existe déjà`));
    });

    it('Affichage du nb de questionnaires par cours',async () => {
        const enseignant2 = "enseignant 2";
        const nom2 = "questionnaire 2";

        expect(qCtrl.getNbQuestionnairesParCours(cours)).toBe(1);
        qCtrl.ajouterQuestionnaire(enseignant2, cours, nom2, description, etat);
        expect(qCtrl.getNbQuestionnairesParCours(cours)).toBe(2);
    });
    
    it('Affichage du nb de fois qu\'une question est utilisée',async () => {
        const question1 = new Question(
            qcours,
            qcategorie,
            qnom,
            qenonce,
            qreponse,
            qretroactionPositive,
            qretroactionNegative,
            enseignant
        );

        const question2 = new Question(
            qcours,
            qcategorie,
            qnom + "2",
            qenonce,
            qreponse,
            qretroactionPositive,
            qretroactionNegative,
            enseignant
        );

        expect(qCtrl.getNbDeFoisQuestionUtilisee(question1)).toBe(0);
        questionnaire?.ajouterQuestion(question1);
        expect(qCtrl.getNbDeFoisQuestionUtilisee(question1)).toBe(1);
        expect(qCtrl.getNbDeFoisQuestionUtilisee(question2)).toBe(0);
    });
});

describe('CU05b postconditions test', () => {
    let questionnaire: Questionnaire;
    let qCtrl: QuestionnaireControleur;

    beforeEach(async() =>  {
        qCtrl = new QuestionnaireControleur();
        qCtrl.ajouterQuestionnaire(enseignant, cours, nom, description, etat);
        questionnaire = qCtrl.recupererQuestionnaire(nom) as Questionnaire;
    });

    it('Nb de questionnaires affichés est bon', async () => {
        expect(qCtrl.getNbQuestionnairesEnseignantParCours(cours, enseignant)).toBe(1);

        qCtrl.ajouterQuestionnaire(enseignant + "2", cours, nom + "2", description, etat);

        expect(qCtrl.getNbQuestionnairesEnseignantParCours(cours, enseignant)).toBe(1);
    });
});

describe('CU05c postconditions test', () => {
    let questionnaire: Questionnaire;
    let qCtrl = new QuestionnaireControleur();
    let questionCtrl: QuestionControleur = questionControleur;

    beforeEach(async() =>  {
        await initControllers;
        qCtrl.ajouterQuestionnaire(enseignant, cours, nom, description, etat);
        questionnaire = qCtrl.recupererQuestionnaire(nom) as Questionnaire;
    });

    it('la description et/ou l\'état a été modifié', async () => {
        const nouvelleEtat = false
        const nouvelleDescription = 'Nouvelle description Test'

        expect(qCtrl.recupererQuestionnaire(cours)._description).toBe(description);
        expect(qCtrl.recupererQuestionnaire(cours)._etat).toBe(etat);

        qCtrl.modifierQuestionnaire(enseignant, cours, nom, nouvelleDescription, nouvelleEtat, null);

        expect(qCtrl.recupererQuestionnaire(cours)._description).toBe(nouvelleDescription);
        expect(qCtrl.recupererQuestionnaire(cours)._etat).toBe(nouvelleEtat);
    });
    
    it('Impossible de modifier un nom avec un déjà existant', async () => {

    })

    it('une question peut être associé à un questionnaire existant', async () => {
        questionCtrl.ajouterQuestion(cours, "test", "test1",
        "Quel est la première ligne du test pour associer une question?",
        true, "Bien joué", "Échec", enseignant)

        const question = questionCtrl.recupererQuestion("test1", enseignant)

        expect(questionnaire._questions.length).toBe(0)

        qCtrl.modifierQuestionnaire(enseignant, cours, nom, description, etat, question.getNom());
        questionnaire = qCtrl.recupererQuestionnaire(nom)

        expect(questionnaire._questions.length).toBe(1)
        expect(questionnaire._questions[0].getCours()).toBe(cours)
        expect(questionnaire._questions[0].getEnseignant()).toBe(enseignant)
    });

    
    it('une question peut être associé à un questionnaire existant', async () => {
        questionCtrl.ajouterQuestion(cours, "test", "test1",
        "Quel est la première ligne du test pour associer une question?",
        true, "Bien joué", "Échec", enseignant)

        const question = questionCtrl.recupererQuestion("test1", enseignant)

        expect(questionnaire._questions.length).toBe(0)

        qCtrl.modifierQuestionnaire(enseignant, cours, nom, description, etat, question.getNom());
        questionnaire = qCtrl.recupererQuestionnaire(nom)

        expect(questionnaire._questions.length).toBe(1)
        expect(questionnaire._questions[0].getCours()).toBe(cours)
        expect(questionnaire._questions[0].getEnseignant()).toBe(enseignant)
    });
});


describe('CU05d postconditions test', () => {
    let qCtrl: QuestionnaireControleur;
    let questionCtrl: QuestionControleur;

    beforeEach(async() =>  {
        qCtrl = new QuestionnaireControleur();
        questionCtrl = new QuestionControleur();
    });

    it('suppression de 2 questionnaires distincts', async () => {
        qCtrl.ajouterQuestionnaire(enseignant, cours, nom, description, etat);
        qCtrl.ajouterQuestionnaire(enseignant, cours, "2eme test", "Description test 2", etat);
        let questionnaire1 = qCtrl.recupererQuestionnaire(nom);
        let questionnaire2 = qCtrl.recupererQuestionnaire("2eme test");

        expect(questionnaire1).toBeDefined()
        expect(questionnaire2).toBeDefined()
        
        qCtrl.supprimerQuestionnaire(enseignant, cours, nom);

        questionnaire1 = qCtrl.recupererQuestionnaire(nom);
        questionnaire2 = qCtrl.recupererQuestionnaire("2eme test");

        expect(questionnaire1).toBeUndefined()
        expect(questionnaire2).toBeDefined()

        qCtrl.supprimerQuestionnaire(enseignant, cours, "2eme test");

        questionnaire1 = qCtrl.recupererQuestionnaire(nom);
        questionnaire2 = qCtrl.recupererQuestionnaire("2eme test");

        expect(questionnaire1).toBeUndefined()
        expect(questionnaire2).toBeUndefined()
    });

    it('suppression de 2 questionnaires distincts', async () => {
        qCtrl.ajouterQuestionnaire(enseignant, cours, nom, description, etat);
        
        questionCtrl.ajouterQuestion(qcours,
            qcategorie,
            qnom,
            qenonce,
            qreponse,
            qretroactionPositive,
            qretroactionNegative,
            enseignant)

        questionCtrl.ajouterQuestion(qcours,
            qcategorie,
            qnom + "(2)",
            qenonce,
            qreponse,
            qretroactionPositive,
            qretroactionNegative,
            enseignant)
        
        let question1 = questionCtrl.recupererQuestion(qnom, enseignant)
        let question2 = questionCtrl.recupererQuestion(qnom + "(2)", enseignant)

        let questionnaire = qCtrl.recupererQuestionnaire(nom);
        
        questionnaire.ajouterQuestion(question1)
        questionnaire.ajouterQuestion(question2)

        expect(question1).toBeDefined()
        expect(question2).toBeDefined()

        expect(questionnaire._questions.length).toBe(2)
        
        qCtrl.supprimerQuestionnaire(enseignant, cours, nom);
        
        question1 = questionCtrl.recupererQuestion(qnom, enseignant)
        question2 = questionCtrl.recupererQuestion(qnom + "(2)", enseignant)

        expect(question1).toBeDefined()
        expect(question2).toBeDefined()
    });

    it('suppression uniquement si le questionnaire a la possibilité d\'être retiré', async () => {
        qCtrl.ajouterQuestionnaire(enseignant, cours, nom, description, etat);
        
        let questionnaire = qCtrl.recupererQuestionnaire(nom);
        questionnaire.setQuestionnaireRemis();
        
        let response = qCtrl.supprimerQuestionnaire(enseignant, cours, nom);

        expect(response).toBe(false);

        questionnaire = qCtrl.recupererQuestionnaire(nom);

        expect(questionnaire).toBeDefined();
    })
})