#include "Database.h"
#include <sqlite3.h>
#include <iostream>
#include <sstream>
#include <iomanip>

// 简单的哈希函数 (仅用于演示，生产环境应使用 bcrypt 等)
#include <functional>

Database::Database(const std::string& dbPath) 
    : m_db(nullptr), m_dbPath(dbPath), m_isOpen(false) {
    // 自动打开数据库
    if (open()) {
        // 初始化表结构
        initializeTables();
    }
}

Database::~Database() {
    close();
}

bool Database::open() {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    int result = sqlite3_open(m_dbPath.c_str(), &m_db);
    if (result != SQLITE_OK) {
        std::cerr << "Failed to open database: " << sqlite3_errmsg(m_db) << std::endl;
        return false;
    }
    
    m_isOpen = true;
    return true;
}

void Database::close() {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (m_db) {
        sqlite3_close(m_db);
        m_db = nullptr;
        m_isOpen = false;
    }
}

bool Database::initializeTables() {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return false;
    
    // 创建用户表
    const char* createUsersTable = R"(
        CREATE TABLE IF NOT EXISTS Users (
            UserID INTEGER PRIMARY KEY AUTOINCREMENT,
            Username TEXT NOT NULL UNIQUE,
            PasswordHash TEXT NOT NULL,
            CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
        );
    )";
    
    // 创建角色表
    const char* createCharactersTable = R"(
        CREATE TABLE IF NOT EXISTS Characters (
            CharacterID INTEGER PRIMARY KEY AUTOINCREMENT,
            UserID INTEGER NOT NULL,
            ClassName TEXT NOT NULL,
            Level INTEGER NOT NULL DEFAULT 1,
            HP INTEGER NOT NULL DEFAULT 100,
            MP INTEGER NOT NULL DEFAULT 50,
            Attack INTEGER NOT NULL DEFAULT 10,
            Speed INTEGER NOT NULL DEFAULT 5,
            FOREIGN KEY(UserID) REFERENCES Users(UserID)
        );
    )";
    
    char* errMsg = nullptr;
    
    if (sqlite3_exec(m_db, createUsersTable, nullptr, nullptr, &errMsg) != SQLITE_OK) {
        std::cerr << "Failed to create Users table: " << errMsg << std::endl;
        sqlite3_free(errMsg);
        return false;
    }
    
    if (sqlite3_exec(m_db, createCharactersTable, nullptr, nullptr, &errMsg) != SQLITE_OK) {
        std::cerr << "Failed to create Characters table: " << errMsg << std::endl;
        sqlite3_free(errMsg);
        return false;
    }
    
    return true;
}

bool Database::executeSql(const std::string& sql) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return false;
    
    char* errMsg = nullptr;
    int result = sqlite3_exec(m_db, sql.c_str(), nullptr, nullptr, &errMsg);
    
    if (result != SQLITE_OK) {
        std::cerr << "SQL error: " << errMsg << std::endl;
        sqlite3_free(errMsg);
        return false;
    }
    
    return true;
}

std::string Database::hashPassword(const std::string& password) {
    // 简单的哈希实现 (仅用于演示)
    std::hash<std::string> hasher;
    size_t hash = hasher(password + "salt_OnlineRpg_2025");
    
    std::ostringstream oss;
    oss << std::hex << std::setw(16) << std::setfill('0') << hash;
    return oss.str();
}

bool Database::verifyPassword(const std::string& password, const std::string& hash) {
    return hashPassword(password) == hash;
}

bool Database::registerUser(const std::string& username, const std::string& password) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return false;
    
    std::string passwordHash = hashPassword(password);
    
    const char* sql = "INSERT INTO Users (Username, PasswordHash) VALUES (?, ?);";
    sqlite3_stmt* stmt;
    
    if (sqlite3_prepare_v2(m_db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
        return false;
    }
    
    sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, passwordHash.c_str(), -1, SQLITE_STATIC);
    
    int result = sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    
    return result == SQLITE_DONE;
}

bool Database::verifyUser(const std::string& username, const std::string& password) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return false;
    
    const char* sql = "SELECT PasswordHash FROM Users WHERE Username = ?;";
    sqlite3_stmt* stmt;
    
    if (sqlite3_prepare_v2(m_db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
        return false;
    }
    
    sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC);
    
    bool verified = false;
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        const char* storedHash = (const char*)sqlite3_column_text(stmt, 0);
        verified = verifyPassword(password, storedHash);
    }
    
    sqlite3_finalize(stmt);
    return verified;
}

bool Database::userExists(const std::string& username) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return false;
    
    const char* sql = "SELECT 1 FROM Users WHERE Username = ?;";
    sqlite3_stmt* stmt;
    
    if (sqlite3_prepare_v2(m_db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
        return false;
    }
    
    sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC);
    
    bool exists = (sqlite3_step(stmt) == SQLITE_ROW);
    sqlite3_finalize(stmt);
    
    return exists;
}

int Database::getUserId(const std::string& username) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return -1;
    
    const char* sql = "SELECT UserID FROM Users WHERE Username = ?;";
    sqlite3_stmt* stmt;
    
    if (sqlite3_prepare_v2(m_db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
        return -1;
    }
    
    sqlite3_bind_text(stmt, 1, username.c_str(), -1, SQLITE_STATIC);
    
    int userId = -1;
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        userId = sqlite3_column_int(stmt, 0);
    }
    
    sqlite3_finalize(stmt);
    return userId;
}

bool Database::createCharacter(int userId, const std::string& className) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return false;
    
    // 根据职业设置初始属性
    int hp = 100, mp = 50, attack = 10, speed = 5;
    if (className == "Warrior") {
        hp = 150; mp = 50; attack = 15; speed = 8;
    } else if (className == "Mage") {
        hp = 100; mp = 100; attack = 20; speed = 10;
    }
    
    const char* sql = "INSERT INTO Characters (UserID, ClassName, HP, MP, Attack, Speed) VALUES (?, ?, ?, ?, ?, ?);";
    sqlite3_stmt* stmt;
    
    if (sqlite3_prepare_v2(m_db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
        return false;
    }
    
    sqlite3_bind_int(stmt, 1, userId);
    sqlite3_bind_text(stmt, 2, className.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int(stmt, 3, hp);
    sqlite3_bind_int(stmt, 4, mp);
    sqlite3_bind_int(stmt, 5, attack);
    sqlite3_bind_int(stmt, 6, speed);
    
    int result = sqlite3_step(stmt);
    sqlite3_finalize(stmt);
    
    return result == SQLITE_DONE;
}

bool Database::getCharacterData(int userId, CharacterData& charData) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return false;
    
    const char* sql = "SELECT * FROM Characters WHERE UserID = ?;";
    sqlite3_stmt* stmt;
    
    if (sqlite3_prepare_v2(m_db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
        return false;
    }
    
    sqlite3_bind_int(stmt, 1, userId);
    
    bool found = false;
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        charData.characterId = sqlite3_column_int(stmt, 0);
        charData.userId = sqlite3_column_int(stmt, 1);
        charData.className = (const char*)sqlite3_column_text(stmt, 2);
        charData.level = sqlite3_column_int(stmt, 3);
        charData.hp = sqlite3_column_int(stmt, 4);
        charData.mp = sqlite3_column_int(stmt, 5);
        charData.attack = sqlite3_column_int(stmt, 6);
        charData.speed = sqlite3_column_int(stmt, 7);
        found = true;
    }
    
    sqlite3_finalize(stmt);
    return found;
}

bool Database::hasCharacter(int userId) {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (!m_isOpen) return false;
    
    const char* sql = "SELECT 1 FROM Characters WHERE UserID = ?;";
    sqlite3_stmt* stmt;
    
    if (sqlite3_prepare_v2(m_db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
        return false;
    }
    
    sqlite3_bind_int(stmt, 1, userId);
    
    bool hasChar = (sqlite3_step(stmt) == SQLITE_ROW);
    sqlite3_finalize(stmt);
    
    return hasChar;
}

std::string Database::getLastError() {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (m_db) {
        return std::string(sqlite3_errmsg(m_db));
    }
    return "Database not open";
}

bool Database::getUserData(const std::string& username, UserData& userData) {
    // Placeholder implementation
    return false;
}

bool Database::updateCharacter(const CharacterData& charData) {
    // Placeholder implementation
    return false;
}

int Database::getLastInsertId() {
    std::lock_guard<std::mutex> lock(m_mutex);
    
    if (m_db) {
        return static_cast<int>(sqlite3_last_insert_rowid(m_db));
    }
    return -1;
}
