/*
 * 数据源管理模块
 * 提供数据库连接和语句执行的接口定义与 Mock 实现
 */

package tybb2026::tycj_orm

import std.collection.*
import std.convert.*

/*
 * 数据库类型枚举
 */
public enum DatabaseType {
    | MySql
    | PostgreSQL
    | Sqlite
    | Oracle
    | SqlServer
}

/*
 * 数据库连接接口
 * 封装数据库连接操作
 */
public interface Connection {
    /*
     * 创建预编译 SQL 语句执行器
     * @param sql SQL 语句
     * @return 预编译语句执行器
     */
    func prepareStatement(sql: String): PreparedStatement

    /*
     * 提交事务
     */
    func commit(): Unit

    /*
     * 回滚事务
     */
    func rollback(): Unit

    /*
     * 关闭连接
     */
    func close(): Unit
}

/*
 * SQL 语句执行器接口
 */
public interface Statement {
    /*
     * 执行任意 SQL 语句
     * @param sql SQL 语句
     * @return 是否有结果集
     */
    func execute(sql: String): Bool

    /*
     * 执行更新语句
     * @param sql SQL 语句
     * @return 影响的行数
     */
    func executeUpdate(sql: String): Int64

    /*
     * 关闭执行器
     */
    func close(): Unit
}

/*
 * 预编译 SQL 语句执行器接口
 * 继承自 Statement
 */
public interface PreparedStatement <: Statement {
    /*
     * 设置字符串参数
     * @param index 参数索引(从1开始)
     * @param value 参数值
     */
    func setString(index: Int64, value: String): Unit

    /*
     * 设置整数参数
     * @param index 参数索引(从1开始)
     * @param value 参数值
     */
    func setInt(index: Int64, value: Int64): Unit

    /*
     * 设置浮点数参数
     * @param index 参数索引(从1开始)
     * @param value 参数值
     */
    func setFloat(index: Int64, value: Float64): Unit

    /*
     * 设置布尔参数
     * @param index 参数索引(从1开始)
     * @param value 参数值
     */
    func setBool(index: Int64, value: Bool): Unit

    /*
     * 执行更新操作(INSERT/UPDATE/DELETE)
     * @return 影响的行数
     */
    func executeUpdate(): Int64

    /*
     * 执行查询操作(SELECT)
     * @return 结果集
     */
    func executeQuery(): ResultSet
}

/*
 * 结果集接口
 */
public interface ResultSet {
    /*
     * 移动到下一行
     * @return 是否有下一行
     */
    func next(): Bool

    /*
     * 根据列名获取字符串值
     * @param columnName 列名
     * @return 列值
     */
    func getString(columnName: String): String

    /*
     * 根据列名获取整数值
     * @param columnName 列名
     * @return 列值
     */
    func getInt(columnName: String): Int64

    /*
     * 根据列名获取浮点数值
     * @param columnName 列名
     * @return 列值
     */
    func getFloat(columnName: String): Float64

    /*
     * 根据列名获取布尔值
     * @param columnName 列名
     * @return 列值
     */
    func getBool(columnName: String): Bool

    /*
     * 检查列值是否为 NULL
     * @param columnName 列名
     * @return 是否为 NULL
     */
    func isNull(columnName: String): Bool

    /*
     * 关闭结果集
     */
    func close(): Unit
}

/*
 * 数据源接口
 * 定义数据源的基本操作
 */
public interface DataSource {
    /*
     * 获取数据库连接
     * @return 数据库连接选项
     */
    func getConnection(): Option<Connection>

    /*
     * 关闭数据源
     */
    func close(): Unit
}

/*
 * 数据库配置类
 * 用于配置数据库连接参数
 */
public class DatabaseConfig {
    /* 数据库类型 */
    public var dbType: DatabaseType
    /* 主机地址 */
    public var host: String
    /* 端口号 */
    public var port: Int64
    /* 数据库名 */
    public var database: String
    /* 用户名 */
    public var username: String
    /* 密码 */
    public var password: String

    public init() {
        this.dbType = DatabaseType.MySql
        this.host = "localhost"
        this.port = 3306
        this.database = ""
        this.username = "root"
        this.password = ""
    }

    /*
     * 创建 MySQL 配置
     * @return 数据库配置
     */
    public static func mysql(): DatabaseConfig {
        let config = DatabaseConfig()
        config.dbType = DatabaseType.MySql
        config.port = 3306
        return config
    }

    /*
     * 创建 SQLite 配置
     * @return 数据库配置
     */
    public static func sqlite(): DatabaseConfig {
        let config = DatabaseConfig()
        config.dbType = DatabaseType.Sqlite
        config.port = 0
        return config
    }

    /*
     * 构建数据库连接 URL
     * @return 连接 URL 字符串
     */
    public func buildUrl(): String {
        match (dbType) {
            case DatabaseType.MySql =>
                return "jdbc:mysql://${host}:${port}/${database}"
            case DatabaseType.PostgreSQL =>
                return "jdbc:postgresql://${host}:${port}/${database}"
            case DatabaseType.Sqlite =>
                return "jdbc:sqlite:${database}"
            case DatabaseType.Oracle =>
                return "jdbc:oracle:thin:@${host}:${port}:${database}"
            case DatabaseType.SqlServer =>
                return "jdbc:sqlserver://${host}:${port};databaseName=${database}"
        }
    }
}

/*
 * Mock 连接实现
 * 用于测试和开发阶段,模拟数据库连接行为
 */
public class MockConnection <: Connection {
    /* 是否已关闭 */
    private var closed: Bool = false

    public func prepareStatement(sql: String): PreparedStatement {
        return MockPreparedStatement(sql: sql)
    }

    public func commit(): Unit {
        // 模拟提交事务
    }

    public func rollback(): Unit {
        // 模拟回滚事务
    }

    public func close(): Unit {
        closed = true
    }
}

/*
 * Mock 预编译语句实现
 * 用于测试和开发阶段,模拟预编译语句行为
 */
public class MockPreparedStatement <: PreparedStatement {
    /* SQL 语句 */
    private let sql: String
    /* 参数列表 */
    private var parameters: ArrayList<String> = ArrayList<String>()

    public init(sql!: String = "") {
        this.sql = sql
    }

    public func setString(index: Int64, value: String): Unit {
        // 确保参数按索引顺序存储
        while (parameters.size < index) {
            parameters.add("")
        }
        parameters[Int64(index - 1)] = value
    }

    public func setInt(index: Int64, value: Int64): Unit {
        while (parameters.size < index) {
            parameters.add("")
        }
        parameters[Int64(index - 1)] = value.toString()
    }

    public func setFloat(index: Int64, value: Float64): Unit {
        while (parameters.size < index) {
            parameters.add("")
        }
        parameters[Int64(index - 1)] = value.toString()
    }

    public func setBool(index: Int64, value: Bool): Unit {
        while (parameters.size < index) {
            parameters.add("")
        }
        parameters[Int64(index - 1)] = if (value) { "1" } else { "0" }
    }

    public func executeUpdate(): Int64 {
        return 1
    }

    public func executeQuery(): ResultSet {
        MockResultSet()
    }

    public func execute(sql: String): Bool {
        return true
    }

    public func executeUpdate(sql: String): Int64 {
        return 1
    }

    public func close(): Unit {
        // 模拟关闭
    }
}

/*
 * Mock 结果集实现
 * 用于测试和开发阶段,模拟结果集行为
 */
public class MockResultSet <: ResultSet {
    /* 数据行列表 */
    private var data: ArrayList<HashMap<String, String>>
    /* 当前行索引 */
    private var rowIndex: Int64 = -1

    public init(data!: ArrayList<HashMap<String, String>> = ArrayList<HashMap<String, String>>()) {
        this.data = data
    }

    public func next(): Bool {
        rowIndex += 1
        return rowIndex < data.size
    }

    public func getString(columnName: String): String {
        if (rowIndex >= 0 && rowIndex < data.size) {
            let row = data[rowIndex]
            match (row.get(columnName)) {
                case Some(val) => return val
                case None => return ""
            }
        }
        return ""
    }

    public func getInt(columnName: String): Int64 {
        if (rowIndex >= 0 && rowIndex < data.size) {
            let row = data[rowIndex]
            match (row.get(columnName)) {
                case Some(val) =>
                    safeParseInt(val)
                case None => 0
            }
        } else {
            0
        }
    }

    public func getFloat(columnName: String): Float64 {
        if (rowIndex >= 0 && rowIndex < data.size) {
            let row = data[rowIndex]
            match (row.get(columnName)) {
                case Some(val) =>
                    safeParseFloat(val)
                case None => 0.0
            }
        } else {
            0.0
        }
    }

    public func getBool(columnName: String): Bool {
        if (rowIndex >= 0 && rowIndex < data.size) {
            let row = data[rowIndex]
            match (row.get(columnName)) {
                case Some(val) =>
                    val == "true" || val == "1"
                case None => false
            }
        } else {
            false
        }
    }

    public func isNull(columnName: String): Bool {
        if (rowIndex >= 0 && rowIndex < data.size) {
            let row = data[rowIndex]
            match (row.get(columnName)) {
                case Some(val) => val.isEmpty()
                case None => true
            }
        } else {
            true
        }
    }

    // 辅助函数:安全解析整数(避免在 lambda/match 中使用 try-catch)
    private static func safeParseInt(val: String): Int64 {
        try {
            return Int64.parse(val)
        } catch (_: Exception) {
            return 0
        }
    }

    // 辅助函数:安全解析浮点数
    private static func safeParseFloat(val: String): Float64 {
        try {
            return Float64.parse(val)
        } catch (_: Exception) {
            return 0.0
        }
    }

    public func close(): Unit {
        // 模拟关闭
    }
}