import conn from '../database.js';

/**
 * Renvoie les derniers avis laissés sur la borne trié par ordre chronologque décroissant
 * @param {Number} limit Nombre d'avis a afficher 
 * @returns Une liste d'objets de la forme {id: id de l'avis, date: date de l'avis, note_principale: note sur 10, commentaire: avis textuel, nom_source, sexe_auteur, age_auteur}
 */
const getLastReviews = (limit=10) => {
    return new Promise((resolve, reject) => {
        let sql = `SELECT borne_avis.id,date,note_principale,commentaire,sources.nom as nom_source, borne_auteurs.sexe as sexe_auteur, borne_auteurs.age as age_auteur
            FROM borne_avis
            JOIN sources ON sources.id = source_id
            JOIN borne_auteurs ON borne_auteurs.id = id_auteur
            ORDER BY borne_avis.id DESC LIMIT ?`;
        conn.query(sql, [limit], (err, res) => {
            if(err) {
                reject(err);
            }else {
                resolve(res)
            }
        })
    })
}

/**
 * Renvoie les informations sur un avis avec un ID spécifique
 * @param {Number} id Id de la review
 * @returns Un objet de la forme des objets dans la table borne_avis ayant l'id id s'il existe, renvoie une erreur sinon
 */
const getReviewFromId = (id) => {
    return new Promise((resolve, reject) => {
        let sql = `SELECT * FROM borne_avis WHERE id = ? LIMIT 1`;
        conn.query(sql, [id], (err, res) => {
            if(err) {
                reject(err);
            }else {
                if(res.length != 1) {
                    reject(new Error("Avis avec cet ID non trouvé"))
                }else {
                    resolve(res[0])
                }
                if(res.length != 1) {
                    reject(new Error("Avis avec cet ID non trouvé"))
                }else {
                    resolve(res[0])
                }
            }
        })
    })
}

/**
 * Renvoie tout les critères de notation valides
 * @returns Une liste d'objets de la forme {id,nom}
 */
const getCriteres = () => {
    return new Promise((resolve, reject) => {
        let sql = `SELECT * FROM borne_criteres`;
        conn.query(sql, [limit], (err, res) => {
            if(err) {
                reject(err);
            }else {
                resolve(res)
            }
        })
    })
}

/**
 * Renvoie les "limit" notes les plus récentes laissées pour un critère spécifié
 * @param {String} critere Nom de critère
 * @param {Number} limit Nombre max de note a afficher
 * @returns une liste d'objets de la forme {id,date,critere,note,avis_id:id de l'avis lié a cette note}
 */
const getNotesAutresFromCritere = (critere,limit=10) => {
    return new Promise((resolve, reject) => {
        let sql = `SELECT borne_notes_autre.id as id,date,borne_criteres.nom as critere, note, avis_id
        FROM borne_notes_autre
        JOIN borne_criteres ON borne_criteres.id = critere_id
        WHERE borne_criteres.nom = ?
        ORDER BY borne_notes_autre.id DESC LIMIT ? ;`;
        conn.query(sql, [critere,limit], (err, res) => {
            if(err) {
                reject(err);
            }else {
                resolve(res)
            }
        })
    })
}

/**
 * Renvoie toutes les notes sur des critères spécifiques laissée pour un avis spécifique
 * @param {Number} reviewId Id de l'avis
 * @returns une liste d'objets de la forme {id,critere:nom du critère, note:note sur 10}
 */
const getNotesAutresFromReview = (reviewId) => {
    return new Promise((resolve, reject) => {
        let sql = `SELECT borne_notes_autre.id as id,borne_criteres.nom as critere, note
            FROM borne_notes_autre
            JOIN borne_criteres on borne_criteres.id = critere_id
            WHERE avis_id = ?
            ORDER BY borne_notes_autre.id DESC`;
        conn.query(sql, [reviewId], (err, res) => {
            if(err) {
                reject(err);
            }else {
                resolve(res)
            }
        })
    })
}

/**
 * Renvoie les dernières statistiques 
 * @param {String} interval Interval de temps de la statistique, valeurs possibles : "jour","mois","semaine","annee"
 * @param {Number} limit Nombre max de stats a renvoyer
 * @returns Une liste d'objet ou chaque objet correspond a une stat sur une periode donnée (par ex une stat hebdo datée du 07/01 correspond a une stat sur la semaine du 01/01 au 07/01), ces objets sont de la forme
 */
const getStats = (interval, limit=10) => {
    return new Promise((resolve, reject) => {
        if(!["jour","mois","semaine","annee"].includes(interval)) {
            reject(new Error("Invalid time interval"));
            return;
        }
        let sql = `SELECT * FROM stats_general_${interval} ORDER BY id DESC LIMIT ?;`;
        conn.query(sql, [limit], (err, res) => {
            if(err) {
                reject(err);
            }else {
                resolve(res)
            }
        })
    })
}

/*
Ces fonction sont des handlers pour les routes express, elles sont appelées par les routes et renvoient les données au format JSON
*/
export const handleGetLastReviews = (req, res) => {
    getLastReviews(req.query.limit)
    .then((reviews) => {
        res.send(reviews);
    })
    .catch((err) => {
        res.status(500).send("Error: " + err.message);
    });
}

export const handleGetReview = (req, res) => {
    getReviewFromId(req.query.id)
    .then((review) => {
        res.send(review);
    })
    .catch((err) => {
        res.status(500).send("Error: " + err.message);
    });
}

export const handleGetCriteres = (req, res) => {
    getCriteres()
    .then((criteres) => {
        res.send(criteres);
    })
    .catch((err) => {
        res.status(500).send("Error: " + err.message);
    });
}

export const handleGetNotesAutres = (req, res) => {
    if(req.query.critere) {
        getNotesAutresFromCritere(req.query.critere, req.query.limit)
        .then((notes) => {
            res.send(notes);
        })
        .catch((err) => {
            res.status(500).send("Error: " + err.message);
        });
    }else if(req.query.id) {
        getNotesAutresFromReview(req.query.id)
        .then((notes) => {
            res.send(notes);
        })
        .catch((err) => {
            res.status(500).send("Error: " + err.message);
        });
    }else {
        res.status(500).send("Error: no critere or id specified");
    }
}

export const handleGetStats = (req, res) => {
    getStats(req.query.interval, req.query.limit)
    .then((stats) => {
        res.send(stats);
    })
    .catch((err) => {
        res.status(500).send("Error: " + err.message);
    });
}