/*
 * Copyright (C) 2020, KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
#include "chatdatabase.h"

#include <QDir>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlDatabase>
#include <QJsonDocument>
#include <QJsonObject>
#include <QSqlError>
#include <QJsonArray>
#include <QMap>
#include <ukui-log4qt.h>
#include <QDateTime>
#include <QFileInfo>

#define CREATE_TABLE_RECORD_SQL "CREATE TABLE IF NOT EXISTS RECORD(ID INT AUTO_INCREMENT, sessionID VARCHAR(36), msgIndex INT, message TEXT, operateTime INTEGER,PRIMARY KEY (ID))"
#define CREATE_TABLE_HISTORY_ID_SQL "CREATE TABLE IF NOT EXISTS HISTORY_ID(ID INT AUTO_INCREMENT, history_id INT, PRIMARY KEY (ID))"
#define INSERT_HISTORY_ID_SQL "INSERT INTO HISTORY_ID(ID, history_id) VALUES (1, 0)"

static ChatDatabase *g_chatDatabase = nullptr;

class ChatDatabase::Private
{
public:
    bool is_open;
    QSqlDatabase base;
};

ChatDatabase::ChatDatabase():
    d(std::make_shared<ChatDatabase::Private>())
{
    initBase();
    createTable();
}

ChatDatabase::~ChatDatabase()
{
    if (d->is_open)
        d->base.close();
}

bool ChatDatabase::insertOne(QString sessionID, int index, QString message)
{
    if (!d->is_open)
        return false;
    QSqlQuery query(d->base);
    QString str = ("INSERT INTO RECORD(sessionID, msgIndex, message, operateTime) VALUES (?, ?, ?, ?)");

    // 获取当前时间戳
    qint64 timestamp = QDateTime::currentDateTime().toSecsSinceEpoch();
    query.prepare(str);
    query.addBindValue(sessionID);
    query.addBindValue(index);
    query.addBindValue(message);
    query.addBindValue(timestamp);

    bool flag = query.exec();
    if(!flag){
        KyInfo() << "Error: insert record error";
        return false;
    }
    return true;
}

bool ChatDatabase::updateOperateTime(QString sessionID, int index)
{
    if (!d->is_open)
        return false;
    QSqlQuery query(d->base);
    QString str = ("UPDATE RECORD SET operateTime = ? WHERE sessionID = ? and msgIndex = ?");

    // 获取当前时间戳
    qint64 timestamp = QDateTime::currentDateTime().toSecsSinceEpoch();

    query.prepare(str);
    query.addBindValue(timestamp);
    query.addBindValue(sessionID);
    query.addBindValue(0);

    bool flag = query.exec();
    if(!flag){
        KyInfo() << "Error: UPDATE record operateTime error";
        return false;
    }
    return true;
}

bool ChatDatabase::deleteBySessionID(QString sessionID)
{
    if (!d->is_open)
        return false;
    QSqlQuery query(d->base);
    QString str = ("DELETE FROM RECORD WHERE sessionID = ?");
    query.prepare(str);
    query.addBindValue(sessionID);
    bool flag = query.exec();
    if(!flag){
        KyInfo() << "Error: delete record error";
        return false;
    }

    return true;
}

bool ChatDatabase::updateFeedback(QString sessionID, int index, QString message)
{
    if (!d->is_open)
        return false;
    QSqlQuery query(d->base);
    QString str = ("UPDATE RECORD SET message = ? WHERE sessionID = ? and msgIndex = ?");

    query.prepare(str);
    query.addBindValue(message);
    query.addBindValue(sessionID);
    query.addBindValue(index);

    bool flag = query.exec();
    if(!flag){
        KyInfo() << "Error: UPDATE record message error";
        return false;
    }
    return true;
}

QStringList ChatDatabase::selectBySessionID(QString sessionID)
{
    if (!d->is_open)
        return {};
    QStringList result;
    QSqlQuery query(d->base);
    QString str = ("SELECT message FROM RECORD WHERE sessionID = ?");
    query.prepare(str);
    query.addBindValue(sessionID);
    bool flag = query.exec();
    if(!flag){
        KyInfo() << "Error: select record error";
        return {};
    }
    while(query.next()){
        QString str = query.value(0).toString();
        result.append(str);
    }
    return result;
}

QStringList ChatDatabase::selectAll()
{
    if (!d->is_open)
        return {};
    QStringList result;
    QSqlQuery query(d->base);
    bool flag = query.exec(QString("SELECT message FROM RECORD"));
    if(!flag){
        KyInfo() << "Error: select record error";
        return {};
    }
    while(query.next()){
        QString str = query.value(0).toString();
        result.append(str);
    }
    return result;
}

QStringList ChatDatabase::selectAllDialogue()
{
    if (!d->is_open)
        return {};

    QSqlQuery query(d->base);
    QStringList dialogueList;
    QSet<QString> addedSessions;

    // 查询所有记录，准备遍历
    bool flag = query.exec(QString("SELECT sessionID, msgIndex, message, operateTime FROM RECORD where msgIndex = 0 ORDER BY operateTime desc"));
    if (!flag) {
        KyInfo() << "Error: select record error";
        return {};
    }
    // 遍历每一项，检查 msgIndex 是否为 0，且 sessionID 是否已添加
    while (query.next()) {
        QString sessionID = query.value("sessionID").toString();
        int msgIndex = query.value("msgIndex").toInt();
        QString messageJson = query.value("message").toString();
        //KyInfo() << "sessionID==" << sessionID << "msgIndex===" << msgIndex << "messageJson===" <<messageJson;
        //KyInfo() << "sessionID" << sessionID;
        if (msgIndex == 0 && !addedSessions.contains(sessionID)) {
            // 解析 messageJson 字符串以提取 msgHead 和 message 字段
            QJsonDocument jsonDoc = QJsonDocument::fromJson(messageJson.toUtf8());
            QJsonObject jsonObj = jsonDoc.object();
            QString msgHead = jsonObj.value("msgHead").toString();
            QString promptIconPath = jsonObj.value("promptIconPath").toString();
            QString message = jsonObj.value("message").toString();
            QString documentName = jsonObj.value("documentName").toString();//文档名称
            QString imagePath = jsonObj.value("imagePath").toString();//图片路径
            message = message.replace("\n", "\\n");
            message = message.replace("\t", "\\t");
            message = message.replace("\"", "\\\"");
            // 若文档名称不为空，并且消息提为空则展示文件名称
            if(message == "" && documentName != ""){
                message = documentName;
            }
            // 若图片路径不为空，并且消息提为空则展示图片路径
            if(message == "" && imagePath != ""){
                QFileInfo fileInfo(imagePath);
                QString fileName = fileInfo.fileName();
                if(fileName != ""){
                    message = fileName;
                }else{
                    message = imagePath;
                }
            }
            // 构建 JSON 字符串
            QString dialogueItem = QString("{\"sessionID\":\"%1\",\"msgHead\":\"%2\",\"message\":\"%3\",\"promptIconPath\":\"%4\"}").arg(sessionID).arg(msgHead).arg(message).arg(promptIconPath);
            dialogueList.append(dialogueItem);
            addedSessions.insert(sessionID);  // 记录已添加的 sessionID
        }
    }

    return dialogueList;
}

int ChatDatabase::selectMaxHistoryId()
{
    // 查询最大history_id
    if (!d->is_open)
        return 0;
    QStringList result;
    QSqlQuery query(d->base);
    QString str = ("SELECT history_id FROM HISTORY_ID WHERE id = 1");
    query.prepare(str);
    bool flag = query.exec();
    if(!flag){
        KyInfo() << "Error: select selectMaxHistoryId error";
        return {};
    }
    int history_id = 0;
    if(query.next()){
        history_id = query.value(0).toInt();
    }
    return history_id;
}

void ChatDatabase::updateMaxHistoryId(int history_id)
{
    KyInfo() << "UPDATE HISTORY_ID ==" << history_id;
    if (!d->is_open)
        return;
    QSqlQuery query(d->base);
    QString str = ("UPDATE HISTORY_ID SET history_id = ? WHERE ID = 1");

    query.prepare(str);
    query.addBindValue(history_id);

    bool flag = query.exec();
    if(!flag){
        KyInfo() << "Error: UPDATE HISTORY_ID error";
    }
}

ChatDatabase *ChatDatabase::getChatDatabase()
{
    if (g_chatDatabase== nullptr) {
        g_chatDatabase = new ChatDatabase;
    }

    return g_chatDatabase;
}

void ChatDatabase::initBase()
{
    d->base = QSqlDatabase::addDatabase("QSQLITE");
    QString config_path = QDir::homePath().append("/.config/kylin-aiassistant");
    if (!QDir().exists(config_path))
        QDir().mkdir(config_path);

    d->base.setDatabaseName(config_path.append("/kylin_aiassistant_database.db"));
    if(!d->base.open())
         KyInfo() << "Error: open database failed!";
    d->is_open = d->base.isOpen();
}

void ChatDatabase::createTable()
{
    if(!d->is_open){
        KyInfo() << "Error: open database failed!";
    }
    QSqlQuery sql_query(d->base);
    if (!sql_query.exec(CREATE_TABLE_RECORD_SQL))
    {
        KyInfo() << "create table record error";
    }
    if (!sql_query.exec(CREATE_TABLE_HISTORY_ID_SQL))
    {
        KyInfo() << "create table HISTORY_ID error";
    }else{
        if (!sql_query.exec(INSERT_HISTORY_ID_SQL)){
            KyInfo() << "insert HISTORY_ID error";
        }
    }
}
