/*
 * repository.cj - 仓库模块
 *
 * 提供类似 Spring Data JPA 的 CRUD 仓库接口和基础实现。
 */

package tybb2026::tycj_orm

import std.collection.*

/*
 * CRUD 仓库接口
 * 定义基本的增删改查操作
 */
public interface CrudRepository<T, ID> {
    /*
     * 保存实体(插入或更新)
     * @param entity 实体对象
     * @return 保存后的实体
     */
    func save(entity: T): T

    /*
     * 批量保存实体
     * @param entities 实体列表
     * @return 保存后的实体列表
     */
    func saveAll(entities: ArrayList<T>): ArrayList<T>

    /*
     * 根据 ID 查找实体
     * @param id 主键值
     * @return 实体选项
     */
    func findById(id: ID): Option<T>

    /*
     * 判断实体是否存在
     * @param id 主键值
     * @return 是否存在
     */
    func existsById(id: ID): Bool

    /*
     * 查询所有实体
     * @return 实体列表
     */
    func findAll(): ArrayList<T>

    /*
     * 根据 ID 列表查询实体
     * @param ids 主键值列表
     * @return 实体列表
     */
    func findAllById(ids: ArrayList<ID>): ArrayList<T>

    /*
     * 统计实体数量
     * @return 实体数量
     */
    func count(): Int64

    /*
     * 根据 ID 删除实体
     * @param id 主键值
     */
    func deleteById(id: ID): Unit

    /*
     * 删除实体
     * @param entity 实体对象
     */
    func delete(entity: T): Unit

    /*
     * 批量删除实体
     * @param entities 实体列表
     */
    func deleteAll(entities: ArrayList<T>): Unit

    /*
     * 删除所有实体
     */
    func deleteAll(): Unit
}

/*
 * 分页排序仓库接口
 * 扩展 CRUD 仓库,支持分页和排序
 */
public interface PagingAndSortingRepository<T, ID> <: CrudRepository<T, ID> {
    /*
     * 分页查询所有实体
     * @param pageable 分页参数
     * @return 分页结果
     */
    func findAll(pageable: Pageable): Page<T>

    /*
     * 排序查询所有实体
     * @param sort 排序参数
     * @return 实体列表
     */
    func findAll(sort: Sort): ArrayList<T>
}

/*
 * 分页参数接口
 */
public interface Pageable {
    /*
     * 获取页码(从 0 开始)
     */
    func getPageNumber(): Int64

    /*
     * 获取每页大小
     */
    func getPageSize(): Int64

    /*
     * 获取偏移量
     */
    func getOffset(): Int64

    /*
     * 获取排序参数
     */
    func getSort(): Sort

    /*
     * 是否有上一页
     */
    func hasPrevious(): Bool

    /*
     * 是否有下一页
     */
    func hasNext(): Bool

    /*
     * 获取上一页分页参数
     */
    func previous(): Pageable

    /*
     * 获取下一页分页参数
     */
    func next(): Pageable

    /*
     * 获取第一页分页参数
     */
    func first(): Pageable
}

/*
 * 排序类
 * 定义排序规则
 */
public class Sort {
    /* 排序规则列表 */
    private var orders: ArrayList<SortOrder>

    public init(orders!: ArrayList<SortOrder> = ArrayList<SortOrder>()) {
        this.orders = orders
    }

    /*
     * 创建升序排序
     * @param property 属性名
     * @return 排序对象
     */
    public static func ascending(property: String): Sort {
        let orders = ArrayList<SortOrder>()
        orders.add(SortOrder(property: property, direction: SortDirection.Asc))
        return Sort(orders: orders)
    }

    /*
     * 创建降序排序
     * @param property 属性名
     * @return 排序对象
     */
    public static func descending(property: String): Sort {
        let orders = ArrayList<SortOrder>()
        orders.add(SortOrder(property: property, direction: SortDirection.Desc))
        return Sort(orders: orders)
    }

    /*
     * 添加升序排序
     * @param property 属性名
     * @return 当前对象
     */
    public func andAscending(property: String): Sort {
        orders.add(SortOrder(property: property, direction: SortDirection.Asc))
        return this
    }

    /*
     * 添加降序排序
     * @param property 属性名
     * @return 当前对象
     */
    public func andDescending(property: String): Sort {
        orders.add(SortOrder(property: property, direction: SortDirection.Desc))
        return this
    }

    /*
     * 获取排序规则列表
     * @return 排序规则列表
     */
    public func getOrders(): ArrayList<SortOrder> {
        return orders
    }

    /*
     * 是否为空
     * @return 是否为空
     */
    public func isEmpty(): Bool {
        return orders.isEmpty()
    }

    /*
     * 转换为 SQL ORDER BY 子句
     * @return SQL 子句
     */
    public func toSql(): String {
        if (orders.isEmpty()) {
            return ""
        }
        let parts = ArrayList<String>()
        for (order in orders) {
            parts.add(order.toSql())
        }
        return "ORDER BY " + joinStrings(parts, ", ")
    }
}

/*
 * 排序规则类(用于 Sort)
 */
public class SortOrder {
    /* 属性名 */
    public let property: String
    /* 排序方向 */
    public let direction: SortDirection

    public init(property!: String = "", direction!: SortDirection = SortDirection.Asc) {
        this.property = property
        this.direction = direction
    }

    /*
     * 是否升序
     * @return 是否升序
     */
    public func isAscending(): Bool {
        match (direction) {
            case SortDirection.Asc => return true
            case SortDirection.Desc => return false
        }
    }

    /*
     * 是否降序
     * @return 是否降序
     */
    public func isDescending(): Bool {
        match (direction) {
            case SortDirection.Asc => return false
            case SortDirection.Desc => return true
        }
    }

    /*
     * 转换为 SQL 排序子句
     * @return SQL 子句
     */
    public func toSql(): String {
        return "${property} ${if (isAscending()) { "ASC" } else { "DESC" }}"
    }
}

/*
 * 排序方向枚举(用于 SortOrder)
 */
public enum SortDirection {
    | Asc
    | Desc
}

/*
 * 分页请求类
 * 实现 Pageable 接口
 */
public class PageRequest <: Pageable {
    /* 页码 */
    private let pageNumber: Int64
    /* 每页大小 */
    private let pageSize: Int64
    /* 排序参数 */
    private let sort: Sort

    public init(pageNumber!: Int64 = 0, pageSize!: Int64 = 10, sort!: Sort = Sort()) {
        this.pageNumber = pageNumber
        this.pageSize = pageSize
        this.sort = sort
    }

    /*
     * 创建分页请求
     * @param page 页码
     * @param size 每页大小
     * @return 分页请求
     */
    public static func of(page: Int64, size: Int64): PageRequest {
        return PageRequest(pageNumber: page, pageSize: size)
    }

    /*
     * 创建带排序的分页请求
     * @param page 页码
     * @param size 每页大小
     * @param sort 排序参数
     * @return 分页请求
     */
    public static func of(page: Int64, size: Int64, sort: Sort): PageRequest {
        return PageRequest(pageNumber: page, pageSize: size, sort: sort)
    }

    public func getPageNumber(): Int64 {
        return pageNumber
    }

    public func getPageSize(): Int64 {
        return pageSize
    }

    public func getOffset(): Int64 {
        return pageNumber * pageSize
    }

    public func getSort(): Sort {
        return sort
    }

    public func hasPrevious(): Bool {
        return pageNumber > 0
    }

    public func hasNext(): Bool {
        return true // 需要总页数才能准确判断
    }

    public func previous(): Pageable {
        if (pageNumber > 0) {
            return PageRequest(pageNumber: pageNumber - 1, pageSize: pageSize, sort: sort)
        }
        return this
    }

    public func next(): Pageable {
        return PageRequest(pageNumber: pageNumber + 1, pageSize: pageSize, sort: sort)
    }

    public func first(): Pageable {
        return PageRequest(pageNumber: 0, pageSize: pageSize, sort: sort)
    }
}

/*
 * 分页结果类
 */
public class Page<T> {
    /* 当前页内容 */
    private let content: ArrayList<T>
    /* 总记录数 */
    private let totalElements: Int64
    /* 分页参数 */
    private let pageable: Pageable

    public init(content!: ArrayList<T> = ArrayList<T>(), totalElements!: Int64 = 0, pageable!: Pageable = PageRequest()) {
        this.content = content
        this.totalElements = totalElements
        this.pageable = pageable
    }

    /*
     * 获取当前页内容
     * @return 内容列表
     */
    public func getContent(): ArrayList<T> {
        return content
    }

    /*
     * 获取总记录数
     * @return 总记录数
     */
    public func getTotalElements(): Int64 {
        return totalElements
    }

    /*
     * 获取总页数
     * @return 总页数
     */
    public func getTotalPages(): Int64 {
        if (pageable.getPageSize() == 0) {
            return 1
        }
        return (totalElements + pageable.getPageSize() - 1) / pageable.getPageSize()
    }

    /*
     * 获取页码
     * @return 页码
     */
    public func getNumber(): Int64 {
        return pageable.getPageNumber()
    }

    /*
     * 获取每页大小
     * @return 每页大小
     */
    public func getSize(): Int64 {
        return pageable.getPageSize()
    }

    /*
     * 获取当前页记录数
     * @return 当前页记录数
     */
    public func getNumberOfElements(): Int64 {
        return content.size
    }

    /*
     * 是否为第一页
     * @return 是否为第一页
     */
    public func isFirst(): Bool {
        return pageable.getPageNumber() == 0
    }

    /*
     * 是否为最后一页
     * @return 是否为最后一页
     */
    public func isLast(): Bool {
        return pageable.getPageNumber() >= getTotalPages() - 1
    }

    /*
     * 是否有下一页
     * @return 是否有下一页
     */
    public func hasNext(): Bool {
        return pageable.getPageNumber() < getTotalPages() - 1
    }

    /*
     * 是否有上一页
     * @return 是否有上一页
     */
    public func hasPrevious(): Bool {
        return pageable.getPageNumber() > 0
    }

    /*
     * 是否为空
     * @return 是否为空
     */
    public func isEmpty(): Bool {
        return content.isEmpty()
    }
}

/*
 * 基础仓库类
 * 提供 CRUD 操作的工具方法(不使用继承)
 */
public class RepositoryHelper {
    /*
     * 构建查询 SQL
     * @param metadata 实体元数据
     * @return 查询构建器
     */
    public static func buildSelectQuery(metadata: EntityMetadata): SelectBuilder {
        let builder = SelectBuilder(metadata.tableName)
        let columns = metadata.getColumnNames()
        for (col in columns) {
            builder.column(col)
        }
        return builder
    }

    /*
     * 构建插入 SQL
     * @param tableName 表名
     * @return 插入构建器
     */
    public static func buildInsertQuery(tableName: String): InsertBuilder {
        return InsertBuilder(tableName)
    }

    /*
     * 构建更新 SQL
     * @param tableName 表名
     * @return 更新构建器
     */
    public static func buildUpdateQuery(tableName: String): UpdateBuilder {
        return UpdateBuilder(tableName)
    }

    /*
     * 构建删除 SQL
     * @param tableName 表名
     * @return 删除构建器
     */
    public static func buildDeleteQuery(tableName: String): DeleteBuilder {
        return DeleteBuilder(tableName)
    }
}

/*
 * Int64 仓库实现类
 * 提供基于 HashMap 的内存存储实现,用于测试
 */
public class Int64Repository<T> <: CrudRepository<T, Int64> {
    /* 内存存储 */
    private var storage: HashMap<Int64, T>
    /* ID 生成器 */
    private var idCounter: Int64 = 0
    /* ID 获取函数 */
    private let getIdFunc: (T) -> Int64
    /* ID 设置函数 */
    private let setIdFunc: (T, Int64) -> Unit

    public init(
        getIdFunc: (T) -> Int64,
        setIdFunc: (T, Int64) -> Unit
    ) {
        this.storage = HashMap<Int64, T>()
        this.getIdFunc = getIdFunc
        this.setIdFunc = setIdFunc
    }

    public func save(entity: T): T {
        let id = getIdFunc(entity)
        
        // 如果 ID 为 0,则生成新 ID
        if (id == 0) {
            idCounter += 1
            setIdFunc(entity, idCounter)
        }
        
        storage[getIdFunc(entity)] = entity
        return entity
    }

    public func saveAll(entities: ArrayList<T>): ArrayList<T> {
        let result = ArrayList<T>()
        for (entity in entities) {
            result.add(save(entity))
        }
        return result
    }

    public func findById(id: Int64): Option<T> {
        return storage.get(id)
    }

    public func existsById(id: Int64): Bool {
        match (findById(id)) {
            case Some(_) => return true
            case None => return false
        }
    }

    public func findAll(): ArrayList<T> {
        let result = ArrayList<T>()
        for ((_, value) in storage) {
            result.add(value)
        }
        return result
    }

    public func findAllById(ids: ArrayList<Int64>): ArrayList<T> {
        let result = ArrayList<T>()
        for (id in ids) {
            match (findById(id)) {
                case Some(entity) => result.add(entity)
                case None => ()
            }
        }
        return result
    }

    public func count(): Int64 {
        return storage.size
    }

    public func deleteById(id: Int64): Unit {
        storage.remove(id)
    }

    public func delete(entity: T): Unit {
        storage.remove(getIdFunc(entity))
    }

    public func deleteAll(entities: ArrayList<T>): Unit {
        for (entity in entities) {
            delete(entity)
        }
    }

    public func deleteAll(): Unit {
        storage.clear()
    }
}

/*
 * String 仓库实现类
 * 提供基于 HashMap 的内存存储实现,用于测试
 */
public class StringRepository<T> <: CrudRepository<T, String> {
    /* 内存存储 */
    private var storage: HashMap<String, T>
    /* ID 获取函数 */
    private let getIdFunc: (T) -> String

    public init(getIdFunc: (T) -> String) {
        this.storage = HashMap<String, T>()
        this.getIdFunc = getIdFunc
    }

    public func save(entity: T): T {
        storage[getIdFunc(entity)] = entity
        return entity
    }

    public func saveAll(entities: ArrayList<T>): ArrayList<T> {
        let result = ArrayList<T>()
        for (entity in entities) {
            result.add(save(entity))
        }
        return result
    }

    public func findById(id: String): Option<T> {
        return storage.get(id)
    }

    public func existsById(id: String): Bool {
        match (findById(id)) {
            case Some(_) => return true
            case None => return false
        }
    }

    public func findAll(): ArrayList<T> {
        let result = ArrayList<T>()
        for ((_, value) in storage) {
            result.add(value)
        }
        return result
    }

    public func findAllById(ids: ArrayList<String>): ArrayList<T> {
        let result = ArrayList<T>()
        for (id in ids) {
            match (findById(id)) {
                case Some(entity) => result.add(entity)
                case None => ()
            }
        }
        return result
    }

    public func count(): Int64 {
        return storage.size
    }

    public func deleteById(id: String): Unit {
        storage.remove(id)
    }

    public func delete(entity: T): Unit {
        storage.remove(getIdFunc(entity))
    }

    public func deleteAll(entities: ArrayList<T>): Unit {
        for (entity in entities) {
            delete(entity)
        }
    }

    public func deleteAll(): Unit {
        storage.clear()
    }
}