var path = require("path"); 
// 引入 Node.js 的 path 模块，用于处理文件和目录的路径

// 获取数据库模型，通过 path.join 拼接当前工作目录和相对路径来引入模块
databaseModule = require(path.join(process.cwd(), "modules/database")); 
// process.cwd() 获取当前工作目录，path.join 用于拼接路径，确保跨平台兼容性

// 引入自定义的 logger 模块，并调用 logger 函数获取日志记录器
var logger = require('../modules/logger').logger();
 // 引入 logger 模块，并调用其 logger 方法获取一个日志记录器实例

/**
 * 创建对象数据
 * 
 * @param  {[type]}   modelName 模型名称，用于标识要创建数据的具体模型
 * @param  {[type]}   obj       要创建的模型对象，包含具体的数据内容
 * @param  {Function} cb        回调函数，用于处理创建操作的结果，第一个参数可能为错误信息，第二个参数为创建成功后的返回结果（如果有）
 */
module.exports.create = function (modelName, obj, cb) {
    // 从 databaseModule 中获取数据库对象
    var db = databaseModule.getDatabase(); // 获取数据库连接或数据库实例
    
    // 根据模型名称获取相应的模型
    var Model = db.models[modelName]; // 从数据库实例的 models 属性中，根据模型名称获取对应的模型
    
    // 调用模型的 create 方法创建对象，将结果传递给回调函数
    Model.create(obj, cb);
 // 使用模型的 create 方法创建新的数据对象，并通过回调函数处理结果
}
/**
 * 获取所有数据
 * 
 * @param  {[type]}   conditions 查询条件，用于筛选数据，包含多种可能的条件设置
 * 查询条件统一规范
 * conditions
 *    {
 *        "columns" : {
 *            字段条件，存储具体字段和其对应的值
 *            "字段名" : "条件值"
 *        },
 *        "offset" : "偏移",  // 用于分页，表示从第几条数据开始查询
 *        "omit" : ["字段"],  // 表示要排除的字段列表
 *        "only" : ["需要字段"],  // 表示只查询的字段列表
 *        "limit" : "",  // 表示查询的数量限制，用于分页
 *        "order" :[ 
 *            "字段", A | Z,  // 表示排序的字段和排序方向（升序或降序）
 *           ...
 *        ]
 *    }
 * @param  {Function} cb         回调函数，用于处理查询结果，第一个参数可能为错误信息，第二个参数为查询到的数据
 */
module.exports.list = function (modelName, conditions, cb) {
    // 从 databaseModule 中获取数据库对象
    var db = databaseModule.getDatabase(); // 获取整个数据库实例或连接
    
    // 根据模型名称获取相应的模型
    var model = db.models[modelName]; // 从数据库实例的 models 属性中，根据传入的模型名称获取对应的模型
    
    // 如果模型不存在，调用回调函数并传递错误信息
    if (!model) return cb("模型不存在", null); // 如果模型未找到，则立即返回错误信息给回调函数
    
    // 初始化查询模型为 find 方法，表示要执行查询操作
    var queryModel = model.find(); // 默认执行全表查询，后续根据条件进行筛选
    
    // 如果存在查询条件，则根据条件进行相应的查询操作
    if (conditions) {
        // 如果指定了需要查询的字段条件
        if (conditions["columns"]) {
            queryModel = queryModel.find(conditions["columns"]); // 根据字段条件进行精确查询
        }
        
        // 如果指定了数据偏移量，用于分页查询
        if (conditions["offset"]) {
            queryModel = queryModel.offset(parseInt(conditions["offset"], 10)); // 解析偏移量为整数，并设置到查询模型中
        }
        
        // 如果指定了查询数量限制
        if (conditions["limit"]) {
            queryModel = queryModel.limit(parseInt(conditions["limit"], 10)); // 解析限制数量为整数，并设置到查询模型中
        }
        
        // 如果指定了只需要查询的字段列表
        if (conditions["only"]) {
            queryModel = queryModel.only(conditions["only"]); // 设置查询模型中只返回这些字段
        }
        
        // 如果指定了要排除的字段列表
        if (conditions["omit"]) {
            queryModel = queryModel.omit(conditions["omit"]); // 设置查询模型中排除这些字段
        }
        
        // 如果指定了排序条件
        if (conditions["order"]) {
            queryModel = queryModel.order(conditions["order"]); // 根据排序条件设置查询模型的排序方式
        }
    }
    
    // 执行查询操作，并将结果传递给回调函数
    queryModel.exec(cb); // 执行查询，并通过回调函数返回结果
}else {
    // 如果没有指定查询条件，则执行全表查询
    model = model.find();
}

// 执行查询操作并处理结果，通过回调函数返回查询结果或错误信息
model.run(function (err, models) { // 注意：这里可能是伪代码或特定框架的API，通常MongoDB等使用exec而不是run
    if (err) {
        // 如果查询过程中发生错误，打印错误信息并通过回调函数返回错误
        console.log(err); // 在生产环境中，通常不会直接打印错误到控制台，而是记录到日志文件中
        return cb("查询失败", null); // 立即返回错误信息给回调函数，不继续执行后续代码
    }
    // 如果查询成功，将查询结果通过回调函数返回
    cb(null, models); // 第一个参数为null表示没有错误，第二个参数为查询到的数据模型数组
});

// 导出根据条件统计数量的函数
module.exports.countByConditions = function (modelName, conditions, cb) {
    // 从 databaseModule 模块中获取数据库连接或实例对象
    var db = databaseModule.getDatabase();
    
    // 根据传入的模型名称从数据库实例的models属性中获取对应的模型
    var model = db.models[modelName];
    
    // 如果指定的模型不存在，则通过回调函数返回错误信息
    if (!model) return cb("模型不存在", null);
    
    // 定义一个内部回调函数，用于处理计数操作的结果
    var resultCB = function (err, count) {
        if (err) {
            // 如果计数过程中发生错误，通过回调函数返回错误
            return cb("查询失败", null);
        }
        // 如果计数成功，将结果（符合条件的记录数）通过回调函数返回
        cb(null, count); // 第一个参数为null表示没有错误，第二个参数为统计到的数量
    };
    
    // 根据传入的条件执行计数操作
    if (conditions) {
        // 如果指定了查询条件
        if (conditions["columns"]) {
            // 如果条件中包含了字段条件，则根据这些条件进行计数
            model = model.count(conditions["columns"], resultCB); // 注意：这里的API可能因框架而异，MongoDB等通常不使用count直接传递条件对象
        } else {
            // 如果没有指定字段条件，则执行全表计数
            model.count(resultCB); // 注意：这里应该直接调用count方法并传入回调函数，而不是重新赋值给model变量，因为count方法通常不返回新的模型实例
        }
    } else {
        // 如果没有指定任何条件，则执行全表计数
        model.count(resultCB); // 同上，这里应该直接调用count方法
    }
    
    // 注意：在上面的代码中，对model的重新赋值（如 model = model.count(...)）可能是不必要的，因为count方法通常不会返回一个新的模型实例用于后续的链式操作。
    // 正确的做法应该是直接调用count方法并传入回调函数，如上面注释所示。
};
/**
 * 获取一条数据
 * @param  {[type]}   modelName  模型名称，用于指定要查找的模型，该名称应与数据库中定义的模型名称一致
 * @param  {[数组/对象]}   conditions  条件集合，包含查找该条数据的具体条件，可以是对象形式或查询构造器
 * @param  {Function} cb         回调函数，用于处理查找结果，第一个参数为错误信息（如有），第二个参数为找到的数据对象
 */
module.exports.findOne = function (modelName, conditions, cb) {
    // 从 databaseModule 模块中获取数据库连接或实例对象
    var db = databaseModule.getDatabase();
    
    // 根据传入的模型名称从数据库实例的models属性中获取对应的模型类
    var Model = db.models[modelName];
    
    // 如果指定的模型不存在，则通过回调函数返回错误信息，并终止后续操作
    if (!Model) return cb("模型不存在", null);
    
    // 如果查询条件为空，则通过回调函数返回错误信息，并终止后续操作
    // 注意：在实际应用中，可能需要更细致的错误处理，比如允许无条件查询（即查询第一条记录）
    if (!conditions) return cb("条件为空", null);
    
    // 调用模型的 one 方法根据提供的条件查找一条数据
    // 注意：这里的 one 方法可能是特定ORM框架提供的，不是所有数据库库或框架都有此方法
    // 如果找不到符合条件的数据，one 方法通常会返回 null 或触发回调函数中的 err 参数
    Model.one(conditions, function (err, obj) {
        // 使用日志记录器记录可能出现的错误，这里使用的是 debug 级别，表示一般性的调试信息
        // 在生产环境中，可能需要根据错误类型调整日志级别，比如使用 error 级别记录严重错误
        logger.debug(err);
        
        // 如果查询过程中发生错误，通过回调函数返回错误信息，并终止后续操作
        if (err) {
            return cb("查询失败", null);
        }
        
        // 如果查询成功，将找到的数据对象通过回调函数返回
        return cb(null, obj);
    });
}

/**
 * 更新对象数据
 * 
 * @param  {[type]}   modelName 模型名称，用于指定要更新的模型，该名称应与数据库中定义的模型名称一致
 * @param  {[type]}   id        数据关键 ID，用于唯一确定要更新的具体数据记录
 * @param  {[对象]}   updateObj 更新对象数据，包含要更新的字段及其新值
 * @param  {Function} cb        回调函数，用于处理更新操作的结果，第一个参数为错误信息（如有），第二个参数为更新操作的结果（可能因数据库库或框架而异）
 */
module.exports.update = function (modelName, id, updateObj, cb) {
    // 从 databaseModule 模块中获取数据库连接或实例对象
    var db = databaseModule.getDatabase();
    
    // 根据传入的模型名称从数据库实例的models属性中获取对应的模型类
    var Model = db.models[modelName];
    
    // 根据提供的 ID 获取要更新的数据对象
    // 注意：这里的 get 方法可能是特定ORM框架提供的，用于根据主键获取数据对象
    // 在某些框架中，可能需要使用 findById 或类似的方法
    Model.get(id, function (err, obj) {
        // 如果获取数据对象过程中发生错误，比如ID不存在，则通过回调函数返回错误信息，并终止后续操作
        if (err) return cb("更新失败", null);
        
        // 如果成功获取到数据对象，则调用其 save 方法更新数据
        // 注意：这里的 save 方法可能是特定ORM框架提供的，用于将数据对象的更改保存到数据库中
        // save 方法通常会接受一个回调函数，用于处理保存操作的结果
        obj.save(updateObj, cb);
        
        // 注意：在某些框架中，可能需要显式地传递更新条件（如ID）给 save 方法，或者 save 方法本身就是根据数据对象的当前状态进行更新的
        // 因此，这里的代码可能需要根据实际使用的数据库库或框架进行调整
    });
}
/**
 * 通过主键 ID 获取对象
 * @param  {[type]}   modelName 模型名称，用于指定要查找的模型，该名称应与数据库中定义的模型名称一致
 * @param  {[type]}   id        主键 ID，用于唯一确定要查找的具体数据记录
 * @param  {Function} cb        回调函数，用于处理查找结果，第一个参数为错误信息（如有），第二个参数为找到的数据对象（如有）
 */
module.exports.show = function (modelName, id, cb) {
    // 从名为 databaseModule 的模块中获取数据库连接或实例对象，该模块应包含 getDatabase 方法
    var db = databaseModule.getDatabase();
    
    // 根据传入的模型名称从数据库实例的 models 属性中获取对应的模型类
    // 这里的 models 属性可能是一个对象，其键为模型名称，值为对应的模型类
    var Model = db.models[modelName];
    
    // 使用模型类的 get 方法根据提供的主键 ID 获取对应的数据对象
    // get 方法通常接受一个回调函数，用于处理获取过程中的结果或错误
    Model.get(id, function (err, obj) {
        // 将获取结果（或错误信息）通过回调函数返回给调用者
        // 如果 err 存在，表示获取过程中发生了错误；如果 obj 存在，表示成功获取到了数据对象
        cb(err, obj);
    });
}

/**
 * 通过主键 ID 删除对象
 * 
 * @param  {[type]}   modelName 模型名称，用于指定要删除的模型，该名称应与数据库中定义的模型名称一致
 * @param  {[type]}   id        主键 ID，用于唯一确定要删除的具体数据记录
 * @param  {Function} cb        回调函数，用于处理删除操作的结果，第一个参数为错误信息（如有），第二个参数在成功时通常为 null 或未定义（因为删除操作不返回被删除的对象）
 */
module.exports.destroy = function (modelName, id, cb) {
    // 从名为 databaseModule 的模块中获取数据库连接或实例对象
    var db = databaseModule.getDatabase();
    
    // 根据传入的模型名称从数据库实例的 models 属性中获取对应的模型类
    var Model = db.models[modelName];
    
    // 使用模型类的 get 方法根据提供的主键 ID 获取要删除的数据对象
    // 注意：在某些 ORM 框架中，可能不需要先获取对象再删除，而是可以直接根据 ID 删除
    // 但这里的代码示例遵循了先获取对象再删除的模式，可能是为了演示或特定框架的要求
    Model.get(id, function (err, obj) {
        // 如果获取对象过程中发生错误（比如 ID 不存在），则通过回调函数返回错误信息
        if (err) return cb("无模型 ID"); // 注意：这里的错误信息可能不够具体，实际应用中应提供更详细的错误信息
        
        // 调用数据对象的 remove 方法删除该对象
        // remove 方法通常也接受一个回调函数，用于处理删除过程中的结果或错误
        obj.remove(function (err) {
            // 如果删除过程中发生错误，则通过回调函数返回错误信息
            if (err) return cb("删除失败"); // 同样，这里的错误信息可能不够具体
            
            // 如果删除成功，则通过回调函数返回 null（或未定义），表示没有错误信息
            return cb(null);
        });
    });
}

/**
 * 通过模型名称获取数据库数量
 * 
 * @param  {[type]}   modelName 模型名称，用于指定要统计数量的模型，该名称应与数据库中定义的模型名称一致
 * @param  {Function} cb        回调函数，用于处理统计结果，第一个参数为错误信息（如有），第二个参数为统计得到的数量
 */
module.exports.count = function (modelName, cb) {
    // 从名为 databaseModule 的模块中获取数据库连接或实例对象
    var db = databaseModule.getDatabase();
    
    // 根据传入的模型名称从数据库实例的 models 属性中获取对应的模型类
    var Model = db.models[modelName];
    
    // 调用模型类的 count 方法统计该模型对应的数据记录数量
    // count 方法通常不接受条件参数（除非特定框架支持），直接统计所有记录的数量
    // 它也接受一个回调函数，用于处理统计过程中的结果或错误
    Model.count(function (err, count) {
        // 注意：这里的回调函数应该有两个参数，但原代码中的 cb 调用只传递了一个（err）
        // 为了保持注释的准确性，我假设原代码是一个简化或错误的示例，并在此处修正
        // 正确的调用应该是 cb(err, count)，即将统计得到的数量也传递给回调函数
        // 但由于原代码未修改，下面的注释仍基于原代码
        
        // 理论上，这里应该将统计结果（或错误信息）通过回调函数返回给调用者
        // 但由于原代码只传递了 err 参数，因此 count 参数被忽略了
        // 为了修正这一点，应该将 cb 调用改为 cb(err, count)（如果这是预期的行为）
        // 但由于要求是不删改原代码，所以下面的注释仍然基于原代码
        
        // 将统计过程中的错误信息（如有）通过回调函数返回给调用者
        // 注意：由于原代码忽略了 count 参数，因此调用者无法获取到统计的数量
        cb(err); // 修正后应为 cb(err, count)，但遵循不删改原代码的原则，此处保留原样
    });
    
    // 注意：上面的 Model.count 调用实际上可能是一个错误，因为大多数 ORM 框架的 count 方法
    // 都会接受一个回调函数作为参数，用于处理统计结果。如果原代码中的 Model.count 方法
    // 确实不接受回调函数（这不太可能），那么这里的代码将无法正常工作。

}
/**

通过条件判断数据是否存在
@param {[type]} modelName 模块名，用于指定要检查是否存在数据的模型
@param {[type]} conditions 条件，用于判断数据是否存在的条件集合
@param {Function} cb 回调函数，用于处理检查结果，第一个参数可能为错误信息，第二个参数为数据是否存在的布尔值
*/
module.exports.exists = function (modelName, conditions, cb) {
// 从 databaseModule 中获取数据库对象
var db = databaseModule.getDatabase(); // 获取全局数据库对象，用于后续操作
// 根据模型名称获取相应的模型
var Model = db.models[modelName]; // 从数据库对象中，通过模型名称获取到具体的模型

// 调用模型的 exists 方法检查数据是否存在，将结果传递给回调函数
Model.exists(conditions, function (err, isExists) { // 调用模型的exists方法，传入条件对象和回调函数
if (err) return cb("查询失败"); // 如果查询过程中出错，则通过回调函数返回错误信息
cb(null, isExists); // 如果没有错误，则通过回调函数返回数据是否存在的布尔值
});
}

/**

获取指定名称的模型
@param {[type]} modelName 模型名，用于指定要获取的模型
@return {[type]} 返回指定名称的模型对象
*/
module.exports.getModel = function (modelName) {
// 从 databaseModule 中获取数据库对象
var db = databaseModule.getDatabase(); // 获取全局数据库对象，用于后续操作
// 根据模型名称获取相应的模型
return db.models[modelName]; // 从数据库对象中，通过模型名称获取到具体的模型，并返回该模型对象
}