/*
 * -------------------------------------------------------------------------
 * This file is part of the MindStudio project.
 * Copyright (c) 2025 Huawei Technologies Co.,Ltd.
 *
 * MindStudio is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *          http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 */
#include <gtest/gtest.h>
#include "Database.h"
#include "../../../DatabaseTestCaseMockUtil.h"
using namespace Dic::Global::PROFILER::MockUtil;
class DataBaseTest : public ::testing::Test {
  protected:
    class MockDatabase : public Dic::Module::Database {
      public:
        explicit MockDatabase(std::recursive_mutex &sqlMutex) : Database(sqlMutex) {}
        void SetDbPtr(sqlite3 *dbPtr) {
            isOpen = true;
            db = dbPtr;
            path = ":memory:";
        }
    };
};

/**
 * 根据表名查询表结构,正常情况
 */
TEST_F(DataBaseTest, TestQueryTableInfoByNameNormal) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    auto res = database.QueryTableInfoByName("decode_gen_speed");
    const uint64_t expectSize = 5;
    EXPECT_EQ(res.size(), expectSize);
    EXPECT_EQ(res.front().key, "timestamp");
    EXPECT_EQ(res.front().type, "TEXT");
    EXPECT_EQ(res.back().key, "p50");
    EXPECT_EQ(res.back().type, "REAL");
}

/**
 * 根据表名查询表结构,sql注入情况
 */
TEST_F(DataBaseTest, TestQueryTableInfoByNameWhenSqlInjectReturnEmpty) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    auto res = database.QueryTableInfoByName("decode_gen_speed()");
    const uint64_t expectSize = 0;
    EXPECT_EQ(res.size(), expectSize);
}

/**
 * 根据表名查询表结构,表名不正确
 */
TEST_F(DataBaseTest, TestQueryTableInfoByNameWhenNameErrReturnEmpty) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    auto res = database.QueryTableInfoByName("SELECT");
    const uint64_t expectSize = 0;
    EXPECT_EQ(res.size(), expectSize);
}

/**
 * 根据表名查询表结构,db未打开
 */
TEST_F(DataBaseTest, TestQueryTableInfoByNameWhenDbNotOpenReturnEmpty) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    database.SetDbPtr(dbPtr);
    auto res = database.QueryTableInfoByName("SELECT");
    const uint64_t expectSize = 0;
    EXPECT_EQ(res.size(), expectSize);
}

/**
 * 根据表名查询表数据量,正常情况
 */
TEST_F(DataBaseTest, TestQueryCountByTableNameNormal) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    std::string dataSql = "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:735760', 6.0869, 6.1759, 6.1512, 6.041);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:44:344296', 2.1341, 2.1451, 2.142, 2.1285);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:736910', 6.0657, 6.1541, 6.1295, 6.0201);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:736935', 6.0652, 6.1537, 6.129, 6.0196);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:736967', 6.0646, 6.1531, 6.1285, 6.0191);";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, dataSql);
    Dic::Module::PageQuery query;
    const std::vector<Dic::Module::ColumnAtt> columns = database.QueryTableInfoByName("decode_gen_speed");
    query.viewName = "decode_gen_speed";
    auto res = database.QueryCountByTableName(query, columns);
    const uint64_t expectSize = 5;
    EXPECT_EQ(res, expectSize);
}

/**
 * 根据表名查询表数据量,搜索情况
 */
TEST_F(DataBaseTest, TestQueryCountByTableNameSearch) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    std::string dataSql = "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:735760', 6.0869, 6.1759, 6.1512, 6.041);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:44:344296', 2.1341, 2.1451, 2.142, 2.1285);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:736910', 6.0657, 6.1541, 6.1295, 6.0201);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:736935', 6.0652, 6.1537, 6.129, 6.0196);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:736967', 6.0646, 6.1531, 6.1285, 6.0191);";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, dataSql);
    Dic::Module::PageQuery query;
    const std::vector<Dic::Module::ColumnAtt> columns = database.QueryTableInfoByName("decode_gen_speed");
    query.viewName = "decode_gen_speed";
    query.pageFilters.push_back({"avg", "6.065"});
    auto res = database.QueryCountByTableName(query, columns);
    const uint64_t expectSize = 2;
    EXPECT_EQ(res, expectSize);
}

/**
 * 根据表名查询表数据量,sql注入情况
 */
TEST_F(DataBaseTest, TestQueryCountByTableNameWhenSqlInjectReturnEmpty) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    Dic::Module::PageQuery query;
    const std::vector<Dic::Module::ColumnAtt> columns = database.QueryTableInfoByName("decode_gen_speed()");
    query.viewName = "decode_gen_speed()";
    auto res = database.QueryCountByTableName(query, columns);
    const uint64_t expectSize = 0;
    EXPECT_EQ(res, expectSize);
}

/**
 * 根据表名查询表数据量,表名不正确
 */
TEST_F(DataBaseTest, TestQueryCountByTableNameWhenNameErrReturnEmpty) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    Dic::Module::PageQuery query;
    const std::vector<Dic::Module::ColumnAtt> columns = database.QueryTableInfoByName("SELECT");
    query.viewName = "SELECT";
    auto res = database.QueryCountByTableName(query, columns);
    const uint64_t expectSize = 0;
    EXPECT_EQ(res, expectSize);
}

/**
 * 根据表名查询表数据量,db未打开
 */
TEST_F(DataBaseTest, TestQueryCountByTableNameWhenDbNotOpenReturnEmpty) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    database.SetDbPtr(dbPtr);
    Dic::Module::PageQuery query;
    const std::vector<Dic::Module::ColumnAtt> columns = database.QueryTableInfoByName("SELECT");
    query.viewName = "SELECT";
    auto res = database.QueryCountByTableName(query, columns);
    const uint64_t expectSize = 0;
    EXPECT_EQ(res, expectSize);
}

/**
 * 分页查询表数据,正常情况
 */
TEST_F(DataBaseTest, TestQueryDataByPageNormal) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    std::string dataSql = "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:646147', NULL, NULL, NULL, NULL);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:646138', NULL, NULL, NULL, NULL);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:735760', 6.0869, 6.1759, 6.1512, 6.041);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:44:344296', 2.1341, 2.1451, 2.142, 2.1285);";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, dataSql);
    auto cols = database.QueryTableInfoByName("decode_gen_speed");
    Dic::Module::PageQuery pageQuery;
    pageQuery.curPage = 1; // 1
    pageQuery.size = 10; // 10
    pageQuery.viewName = "decode_gen_speed";
    auto res = database.QueryDataByPage(pageQuery, cols);
    const uint64_t expectSize = 4;
    EXPECT_EQ(res.size(), expectSize);
    EXPECT_EQ(res.front()[cols.front().key], "2025-03-28 22:57:43:646147");
    EXPECT_EQ(res.front()[cols.back().key], "0");
    EXPECT_EQ(res.back()[cols.front().key], "2025-03-28 22:57:44:344296");
    EXPECT_EQ(res.back()[cols.back().key], "2.1285");
}

/**
 * 分页查询表数据,搜索情况
 */
TEST_F(DataBaseTest, TestQueryDataByPageSearch) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    std::string dataSql = "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:646147', NULL, NULL, NULL, NULL);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:646138', NULL, NULL, NULL, NULL);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:735760', 6.0869, 6.1759, 6.1512, 6.041);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:44:344296', 2.1341, 2.1451, 2.142, 2.1285);";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, dataSql);
    auto cols = database.QueryTableInfoByName("decode_gen_speed");
    Dic::Module::PageQuery pageQuery;
    pageQuery.curPage = 1; // 1
    pageQuery.size = 10; // 10
    pageQuery.viewName = "decode_gen_speed";
    pageQuery.pageFilters.push_back({"timestamp", "646"});
    auto res = database.QueryDataByPage(pageQuery, cols);
    const uint64_t expectSize = 2;
    EXPECT_EQ(res.size(), expectSize);
    EXPECT_EQ(res.front()[cols.front().key], "2025-03-28 22:57:43:646147");
    EXPECT_EQ(res.front()[cols.back().key], "0");
    EXPECT_EQ(res.back()[cols.front().key], "2025-03-28 22:57:43:646138");
    EXPECT_EQ(res.back()[cols.back().key], "0");
}

/**
 * 分页查询表数据,有排序条件
 */
TEST_F(DataBaseTest, TestQueryDataByPageWhenOrderAndLimit) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"decode_gen_speed\" (\n"
                      "\"timestamp\" TEXT,\n"
                      "  \"avg\" REAL,\n"
                      "  \"p99\" REAL,\n"
                      "  \"p90\" REAL,\n"
                      "  \"p50\" REAL\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    std::string dataSql = "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:735760', 6.0869, 6.1759, 6.1512, 6.041);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:44:344296', 2.1341, 2.1451, 2.142, 2.1285);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:736910', 6.0657, 6.1541, 6.1295, 6.0201);\n"
                          "INSERT INTO \"main\".\"decode_gen_speed\" (\"timestamp\", \"avg\", \"p99\", \"p90\", "
                          "\"p50\") VALUES ('2025-03-28 22:57:43:736935', 6.0652, 6.1537, 6.129, 6.0196);";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, dataSql);
    auto cols = database.QueryTableInfoByName("decode_gen_speed");
    Dic::Module::PageQuery pageQuery;
    pageQuery.curPage = 1; // 1
    pageQuery.size = 2; // 2
    pageQuery.viewName = "decode_gen_speed";
    pageQuery.orderBy = "timestamp";
    pageQuery.order = "descend";
    auto res = database.QueryDataByPage(pageQuery, cols);
    const uint64_t expectSize = 2;
    EXPECT_EQ(res.size(), expectSize);
    EXPECT_EQ(res.front()[cols.front().key], "2025-03-28 22:57:44:344296");
    EXPECT_EQ(res.front()[cols.back().key], "2.1285");
    EXPECT_EQ(res.back()[cols.front().key], "2025-03-28 22:57:43:736935");
    EXPECT_EQ(res.back()[cols.back().key], "6.0196");
}

/**
 * 查询翻译正常
 */
TEST_F(DataBaseTest, TestQueryTranslateNormal) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"translate\" (\n"
                      "  \"key\" TEXT NOT NULL,\n"
                      "  \"value_en\" TEXT,\n"
                      "  \"value_zh\" TEXT,\n"
                      "  PRIMARY KEY (\"key\")\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    std::string dataSql = "INSERT INTO \"main\".\"translate\" (\"key\", \"value_en\", \"value_zh\") VALUES "
                          "('request_data', 'bbbb', 'nnnn');\n"
                          "INSERT INTO \"main\".\"translate\" (\"key\", \"value_en\", \"value_zh\") VALUES "
                          "('batch_info', 'ffff', 'mmm');\n"
                          "INSERT INTO \"main\".\"translate\" (\"key\", \"value_en\", \"value_zh\") VALUES "
                          "('kvcache_usage', 'sssss', 'kkk');";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, dataSql);
    auto cols = database.QueryTranslate(false);
    const uint64_t expectSize = 3;
    EXPECT_EQ(cols.size(), expectSize);
    EXPECT_EQ(cols["request_data"], "bbbb");
    cols = database.QueryTranslate(true);
    EXPECT_EQ(cols.size(), expectSize);
    EXPECT_EQ(cols["request_data"], "nnnn");
}

/**
 * 查询翻译不正常
 */
TEST_F(DataBaseTest, TestQueryTranslateAbnormal) {
    std::recursive_mutex sqlMutex;
    MockDatabase database(sqlMutex);
    sqlite3 *dbPtr = nullptr;
    DatabaseTestCaseMockUtil::OpenDB(dbPtr);
    database.SetDbPtr(dbPtr);
    std::string sql = "CREATE TABLE \"translates\" (\n"
                      "  \"key\" TEXT NOT NULL,\n"
                      "  \"value_en\" TEXT,\n"
                      "  \"value_zh\" TEXT,\n"
                      "  PRIMARY KEY (\"key\")\n"
                      ");";
    DatabaseTestCaseMockUtil::InsertData(dbPtr, sql);
    auto cols = database.QueryTranslate(false);
    const uint64_t expectSize = 0;
    EXPECT_EQ(cols.size(), expectSize);
}