#include "databaselms.h"

#include <QtSql>
#include <QSqlDatabase>
#include <QSqlDriver>


QList<Trainee> DataBaseLMS::selectAllTrainees()
{
    bool resBool = false;

    QList<Trainee> listTrainees;

    resBool = db->transaction();

    QString queryStr = QString("SELECT users.user_id, users.name, users.login, users.password, users.archived, users.logged_in, "
                                                 "groups.group_id, groups.name, "
                                                 "computers.computer_id, computers.name, computers.ip_address, "
                                                 "classrooms.classroom_id, classrooms.name "
                                                 "FROM public.users JOIN public.groups ON groups.group_id = users.fk_group_id "
                                                 "LEFT OUTER JOIN public.computers ON computers.computer_id = users.fk_computer_id "
                                                 "LEFT OUTER JOIN public.classrooms ON classrooms.classroom_id = computers.fk_classroom_id "
                                                 "WHERE users.type = '%1' "
                                                 "ORDER BY groups.name, users.name ASC").arg(
                                                    TypeUserDBTrainee);

    QSqlQuery query = QSqlQuery(*db);

    if(queryExec(queryStr, &query))
    {
        while (query.next())
        {//Обучаемый
            Trainee trainee;

            trainee.setID(query.value(0).toInt());
            trainee.setName(query.value(1).toString());
            trainee.setLogin(query.value(2).toString());
            trainee.setPassword(query.value(3).toString());
            trainee.setArchived(query.value(4).toBool());
            trainee.setLoggedIn(query.value(5).toBool());

            Group group = Group(query.value(6).toInt(), query.value(7).toString());
            trainee.setGroup(group);

            Classroom classroom = Classroom(query.value(11).toInt(), query.value(12).toString());
            Computer computer = Computer(query.value(8).toInt(), query.value(9).toString(), query.value(10).toString(), classroom);
            trainee.setComputer(computer);

            //Тайминг
            TimingOfTrainee timing(trainee.getID());

            QString queryStrSELtiming = QString("SELECT timings.timing_id, timings.entry_time, timings.exit_time, timings.operating_time, timings.fk_trainee_id "
                                            "FROM public.timings "
                                            "WHERE fk_trainee_id = '%1'").arg(trainee.getID());

            QSqlQuery querySelTiming = QSqlQuery(*db);

            if(queryExec(queryStrSELtiming, &querySelTiming))
            {
                if (querySelTiming.first())
                {//Тайминг
                    timing.setID(querySelTiming.value(0).toInt());
                    timing.setEntryTime(querySelTiming.value(1).toDateTime());
                    timing.setExitTime(querySelTiming.value(2).toDateTime());
                    timing.setOperatingTime(querySelTiming.value(3).toTime());
                    timing.setTraineeID(querySelTiming.value(4).toInt());
                }

                trainee.setTiming(timing);
            }
            else
            {
                resBool = db->rollback();
                return QList<Trainee>();
            }

            listTrainees.append(trainee);
        }
    }
    else
    {
        resBool = db->rollback();
        return QList<Trainee>();
    }

    resBool = db->commit();
    return listTrainees;
}

Trainee DataBaseLMS::selectTrainee(int id_trainee)
{
    Trainee trainee;

    QString queryStr = QString("SELECT users.user_id, users.name, users.login, users.password, users.archived, users.logged_in, "
                                                 "groups.group_id, groups.name, "
                                                 "computers.computer_id, computers.name, computers.ip_address, "
                                                 "classrooms.classroom_id, classrooms.name "
                                                 "FROM public.users JOIN public.groups ON groups.group_id = users.fk_group_id "
                                                 "LEFT OUTER JOIN public.computers ON computers.computer_id = users.fk_computer_id "
                                                 "LEFT OUTER JOIN public.classrooms ON classrooms.classroom_id = computers.fk_classroom_id "
                                                 "WHERE users.user_id = %1 AND users.type = '%2' "
                                                 "ORDER BY groups.name, users.name ASC").arg(
                                                        QString::number(id_trainee),
                                                        TypeUserDBTrainee);

    QSqlQuery query = QSqlQuery(*db);

    if(queryExec(queryStr, &query))
    {
        if (query.first())
        {//Обучаемый
            trainee.setID(query.value(0).toInt());
            trainee.setName(query.value(1).toString());
            trainee.setLogin(query.value(2).toString());
            trainee.setPassword(query.value(3).toString());
            trainee.setArchived(query.value(4).toBool());
            trainee.setLoggedIn(query.value(5).toBool());

            Group group = Group(query.value(6).toInt(), query.value(7).toString());
            trainee.setGroup(group);

            Classroom classroom = Classroom(query.value(11).toInt(), query.value(12).toString());
            Computer computer = Computer(query.value(8).toInt(), query.value(9).toString(), query.value(10).toString(), classroom);
            trainee.setComputer(computer);
        }
    }

    return trainee;
}

QList<Trainee> DataBaseLMS::selectAllTraineesInGroup(int id_group)
{
    QList<Trainee> listTrainees;

    QString queryStr = QString("SELECT users.user_id, users.name, users.login, users.password, users.archived, users.logged_in, "
                                                 "groups.group_id, groups.name, "
                                                 "computers.computer_id, computers.name, computers.ip_address, "
                                                 "classrooms.classroom_id, classrooms.name "
                                                 "FROM public.users JOIN public.groups ON groups.group_id = users.fk_group_id "
                                                 "LEFT OUTER JOIN public.computers ON computers.computer_id = users.fk_computer_id "
                                                 "LEFT OUTER JOIN public.classrooms ON classrooms.classroom_id = computers.fk_classroom_id "
                                                 "WHERE users.fk_group_id = %1 AND users.type = '%2' "
                                                 "ORDER BY groups.name, users.name ASC").arg(
                                                        QString::number(id_group),
                                                        TypeUserDBTrainee);

    QSqlQuery query = QSqlQuery(*db);

    if(queryExec(queryStr, &query))
    {
        while (query.next())
        {//Обучаемый
            Trainee trainee;

            trainee.setID(query.value(0).toInt());
            trainee.setName(query.value(1).toString());
            trainee.setLogin(query.value(2).toString());
            trainee.setPassword(query.value(3).toString());
            trainee.setArchived(query.value(4).toBool());
            trainee.setLoggedIn(query.value(5).toBool());

            Group group = Group(query.value(6).toInt(), query.value(7).toString());
            trainee.setGroup(group);

            Classroom classroom = Classroom(query.value(11).toInt(), query.value(12).toString());
            Computer computer = Computer(query.value(8).toInt(), query.value(9).toString(), query.value(10).toString(), classroom);
            trainee.setComputer(computer);

            listTrainees.append(trainee);
        }
    }

    return listTrainees;
}

QString DataBaseLMS::selectTraineeNameOnComputer(QString computer_name)
{
    QString queryStr = QString("SELECT users.name "
                                                 "FROM public.users JOIN public.computers ON computers.computer_id = users.fk_computer_id "
                                                 "WHERE computers.name = '%1' AND users.type = '%2' ").arg(
                                                        computer_name,
                                                        TypeUserDBTrainee);

    return queryExecString(queryStr);
}

Trainee DataBaseLMS::selectTraineeOnComputer(QString computer_name)
{
    Trainee trainee;

    QString queryStr = QString("SELECT users.trainee_id, users.name, users.login, users.password, users.archived, users.logged_in, "
                                                 "groups.group_id, groups.name, "
                                                 "computers.computer_id, computers.name, computers.ip_address, "
                                                 "classrooms.classroom_id, classrooms.name "
                                                 "FROM public.users JOIN public.groups ON groups.group_id = users.fk_group_id "
                                                 "LEFT OUTER JOIN public.computers ON computers.computer_id = users.fk_computer_id "
                                                 "LEFT OUTER JOIN public.classrooms ON classrooms.classroom_id = computers.fk_classroom_id "
                                                 "WHERE computers.name = '%1' AND users.type = '%2' ").arg(
                                                        computer_name,
                                                        TypeUserDBTrainee);

    QSqlQuery query = QSqlQuery(*db);

    if(queryExec(queryStr, &query))
    {
        if (query.first())
        {//Обучаемый
            trainee.setID(query.value(0).toInt());
            trainee.setName(query.value(1).toString());
            trainee.setLogin(query.value(2).toString());
            trainee.setPassword(query.value(3).toString());
            trainee.setArchived(query.value(4).toBool());
            trainee.setLoggedIn(query.value(5).toBool());

            Group group = Group(query.value(6).toInt(), query.value(7).toString());
            trainee.setGroup(group);

            Classroom classroom = Classroom(query.value(11).toInt(), query.value(12).toString());
            Computer computer = Computer(query.value(8).toInt(), query.value(9).toString(), query.value(10).toString(), classroom);
            trainee.setComputer(computer);
        }
    }

    return trainee;
}

int DataBaseLMS::insertTrainee(int id_group)
{
    QString queryStr = QString("INSERT INTO public.users (type, name, login, password, archived, logged_in, fk_group_id) "
                                                 "VALUES ('%1', DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, %2) "
                                                 "RETURNING users.user_id").arg(
                                                        TypeUserDBTrainee,
                                                        QString::number(id_group));

    return queryExecInt(queryStr);
}

int DataBaseLMS::insertTrainee(Trainee trainee)
{
    QString queryStr = QString("INSERT INTO public.users (type, name, login, password, archived, logged_in, fk_group_id) "
                                                 "VALUES ('%1', '%2', '%3', '%4', %5, %6, %7) "
                                                 "RETURNING users.user_id").arg(
                                                        TypeUserDBTrainee,
                                                        trainee.getName(),
                                                        trainee.getLogin(),
                                                        trainee.getPassword(),
                                                        trainee.getArchived() ? "true" : "false",
                                                        trainee.getLoggedIn() ? "true" : "false",
                                                        QString::number(trainee.getGroup().getID()));

    return queryExecInt(queryStr);
}

int DataBaseLMS::deleteTrainee(int id_trainee)
{
    QString queryStr;
    int res = 0;
    bool resBool = false;

    resBool = db->transaction();


    //Удаление задач AMM
    /*Выборка задач AMM для этого обучаемого*/
    queryStr = QString("SELECT tasks_amm.task_id "
                                                 "FROM public.tasks_amm "
                                                 "WHERE tasks_amm.fk_trainee_id = %1 "
                                                 "ORDER BY tasks_amm.task_id ASC").arg(
                                                        id_trainee);

    QSqlQuery queryTasksAMMSEL = QSqlQuery(*db);
    if(queryExec(queryStr, &queryTasksAMMSEL))
    {
        while (queryTasksAMMSEL.next())
        {//Задача
            int task_id = queryTasksAMMSEL.value(0).toInt();

            queryStr = QString("DELETE FROM public.subprocs "
                                                         "WHERE fk_task_amm_id = %1 ").arg(
                                                                QString::number(task_id));

            QSqlQuery querySubProcDEL = QSqlQuery(*db);
            if(!queryExec(queryStr, &querySubProcDEL))
            {
                resBool = db->rollback();
                return 0;
            }
        }
    }
    else
    {
        resBool = db->rollback();
        return 0;
    }


    queryStr = QString("DELETE FROM public.tasks_amm "
                                                     "WHERE fk_trainee_id = %1 ").arg(
                                                            QString::number(id_trainee));

    QSqlQuery queryTasksAMMDEL = QSqlQuery(*db);
    if(!queryExec(queryStr, &queryTasksAMMDEL))
    {
        resBool = db->rollback();
        return 0;
    }


    //Удаление задач FIM

    /*Выборка задач FIM для этого обучаемого*/
    queryStr = QString("SELECT tasks_fim.task_id "
                                                 "FROM public.tasks_fim "
                                                 "WHERE tasks_fim.fk_trainee_id = %1 "
                                                 "ORDER BY tasks_fim.task_id ASC").arg(
                                                        id_trainee);

    QSqlQuery queryTasksFIMSEL = QSqlQuery(*db);
    if(queryExec(queryStr, &queryTasksFIMSEL))
    {
        while (queryTasksFIMSEL.next())
        {//Задача
            int task_id = queryTasksFIMSEL.value(0).toInt();

            /*Выборка неисправностей для этой задачи*/
            queryStr = QString("SELECT malfunctions.malfunction_id "
                                                         "FROM public.malfunctions "
                                                         "WHERE malfunctions.fk_task_fim_id = %1 "
                                                         "ORDER BY malfunctions.malfunction_id ASC").arg(
                                                                task_id);

            QSqlQuery queryMulfSEL = QSqlQuery(*db);
            if(queryExec(queryStr, &queryMulfSEL))
            {
                while (queryMulfSEL.next())
                {//Неисправность
                    int mulf_id = queryMulfSEL.value(0).toInt();

                    /*Удаление сигналов для этой неисправности*/
                    queryStr = QString("DELETE FROM public.malf_signs "
                                                                     "WHERE malf_signs.fk_malfunction_id = %1 ").arg(
                                                                            mulf_id);
                    QSqlQuery querySign = QSqlQuery(*db);
                    if(!queryExec(queryStr, &querySign))
                    {
                        resBool = db->rollback();
                        return 0;
                    }
                };

            }
            else
            {
                resBool = db->rollback();
                return 0;
            }

            /*Удаление неисправностей*/
            queryStr = QString("DELETE FROM public.malfunctions "
                                                             "WHERE malfunctions.fk_task_fim_id = %1 ").arg(
                                                                    task_id);
            QSqlQuery queryMulfDEL = QSqlQuery(*db);
            if(!queryExec(queryStr, &queryMulfDEL))
            {
                resBool = db->rollback();
                return 0;
            }

            /*Удаление отчетов для задачи*/
            /*Выборка отчетов для этой задачи*/
            queryStr = QString("SELECT reports.report_id "
                                                         "FROM public.reports "
                                                         "WHERE reports.fk_task_fim_id = %1 "
                                                         "ORDER BY reports.report_id ASC").arg(
                                                                task_id);
            QSqlQuery queryReportsSEL = QSqlQuery(*db);
            if(queryExec(queryStr, &queryReportsSEL))
            {
                while (queryReportsSEL.next())
                {//отчет
                    int report_id = queryReportsSEL.value(0).toInt();

                    /*Удаление items для этого отчета*/
                    queryStr = QString("DELETE FROM public.report_items "
                                                                     "WHERE report_items.fk_report_id = %1 ").arg(
                                                                            report_id);
                    QSqlQuery queryReportDEL = QSqlQuery(*db);
                    if(!queryExec(queryStr, &queryReportDEL))
                    {
                        resBool = db->rollback();
                        return 0;
                    }
                };

            }
            else
            {
                resBool = db->rollback();
                return 0;
            }

            /*Удаление отчетов*/
            queryStr = QString("DELETE FROM public.reports "
                                                             "WHERE reports.fk_task_fim_id = %1 ").arg(
                                                                    task_id);
            QSqlQuery queryReportsDEL = QSqlQuery(*db);
            if(!queryExec(queryStr, &queryReportsDEL))
            {
                resBool = db->rollback();
                return 0;
            }
            // ////////////////////////////
        };
    }
    else
    {
        resBool = db->rollback();
        return 0;
    }

    /*Удаление непосредственно задач FIM*/
    queryStr = QString("DELETE FROM public.tasks_fim "
                                                     "WHERE fk_trainee_id = %1 ").arg(
                                                            QString::number(id_trainee));

    QSqlQuery queryTasksFIMDEL = QSqlQuery(*db);
    if(!queryExec(queryStr, &queryTasksFIMDEL))
    {
        resBool = db->rollback();
        return 0;
    }

    /*Удаление таймингов для обучаемого*/
    queryStr = QString("DELETE FROM public.timings "
                                                     "WHERE fk_trainee_id = %1 ").arg(
                                                            QString::number(id_trainee));

    QSqlQuery queryTimingsDEL = QSqlQuery(*db);
    if(!queryExec(queryStr, &queryTimingsDEL))
    {
        resBool = db->rollback();
        return 0;
    }
    // ////////////////////////////


    //Удаление обучаемого
    queryStr = QString("DELETE FROM public.users "
                                                 "WHERE user_id = %1 AND users.type = '%2' "
                                                 "RETURNING users.user_id").arg(
                                                        QString::number(id_trainee),
                                                        TypeUserDBTrainee);

    res = queryExecInt(queryStr);
    if(res)
    {
        resBool = db->commit();
        return res;
    }
    else
    {
        resBool = db->rollback();
        return 0;
    }
}

int DataBaseLMS::updateTrainee(Trainee trainee)
{
    QString computer_id = (trainee.getComputer().getID() == 0 ? QStringLiteral("null") : QString::number(trainee.getComputer().getID()));

    QString queryStr = QString("UPDATE public.users "
                                                 "SET name = '%1', login = '%2', password = '%3', archived = %4, logged_in = %5, "
                                                 "fk_group_id = %6, "
                                                 "fk_computer_id = %7 "
                                                 "WHERE user_id = %8 AND users.type = '%9' "
                                                 "RETURNING users.user_id").arg(
                                                        trainee.getName(),
                                                        trainee.getLogin(),
                                                        trainee.getPassword(),
                                                        trainee.getArchived() ? "true" : "false",
                                                        trainee.getLoggedIn() ? "true" : "false",
                                                        QString::number(trainee.getGroup().getID()),
                                                        computer_id,
                                                        QString::number(trainee.getID()),
                                                        TypeUserDBTrainee);

    return queryExecInt(queryStr);
}

int DataBaseLMS::insertTimingTrainee(int id_trainee)
{
    QString queryStr = QString("INSERT INTO public.timings (entry_time, exit_time, operating_time, fk_trainee_id) "
                                                 "VALUES (DEFAULT, DEFAULT, DEFAULT, %1) "
                                                 "RETURNING timings.timing_id").arg(
                                                        QString::number(id_trainee));

    return queryExecInt(queryStr);
}

int DataBaseLMS::updateTimingTrainee(int id_trainee, TimingOfTrainee timing)
{
    QString queryStr = QString("UPDATE public.timings "
                                                 "SET entry_time = '%1', exit_time = '%2', operating_time = '%3', fk_trainee_id = %4 "
                                                 "WHERE timing_id = %5 "
                                                 "RETURNING timings.timing_id").arg(
                                                        timing.getEntryTimeS(),
                                                        timing.getExitTimeS(),
                                                        timing.getOperatingTimeS(),
                                                        QString::number(id_trainee),
                                                        QString::number(timing.getID()) );

    return queryExecInt(queryStr);
}

TimingOfTrainee DataBaseLMS::selectTimingTrainee(int id_trainee)
{
    TimingOfTrainee timing(id_trainee);

    QString queryStr = QString("SELECT timings.timing_id, timings.entry_time, timings.exit_time, timings.operating_time, timings.fk_trainee_id "
                                    "FROM public.timings "
                                    "WHERE fk_trainee_id = '%1'").arg(id_trainee);

    QSqlQuery querySel = QSqlQuery(*db);

    if(queryExec(queryStr, &querySel))
    {
        if (querySel.first())
        {//Тайминг
            timing.setID(querySel.value(0).toInt());
            timing.setEntryTime(querySel.value(1).toDateTime());
            timing.setExitTime(querySel.value(2).toDateTime());
            timing.setOperatingTime(querySel.value(3).toTime());
            timing.setTraineeID(querySel.value(4).toInt());
        }
    }

    return timing;
}
