<?php
declare(strict_types=1);

/**
 * 模型基类
 * 数据库连接支持构造函数注入（方便测试时替换为 mock），不传时默认使用 Db::instance() 的 default 连接
 */
abstract class Model
{
    public function __construct(protected ?Db $db = null)
    {
        $this->db ??= Db::instance();
    }

    /**
     * 分页查询
     * @param string $table 表名
     * @param array $where 查询条件（medoo 风格）
     * @param int $page 当前页，从 1 开始
     * @param int $pagesize 每页条数
     * @param array|null $join 关联查询条件（medoo 风格），不需要关联时为 null
     * @param array|string|null $column 查询列，配合 $join 使用
     * @return array{page:int,pagesize:int,total:int,records:int,limit:int}
     */
    public function paging(
        string $table,
        array $where,
        int $page = 1,
        int $pagesize = 50,
        ?array $join = null,
        array|string|null $column = null
    ): array {
        $page = max(1, $page);
        $pagesize = $pagesize ?: 50;

        if (!empty($where['GROUP'])) {
            $records = $this->countGroupedRows($table, $where, $join, $column);
        } else {
            $records = $join
                ? $this->db->count($table, $join, $column, $where)
                : $this->db->count($table, $where);
        }

        return [
            'page'     => $page,
            'pagesize' => $pagesize,
            'total'    => (int) ceil($records / $pagesize),
            'records'  => (int) $records,
            'limit'    => ($page - 1) * $pagesize,
        ];
    }

    /**
     * 带 GROUP BY 的查询，统计去重分组后的总记录数
     */
    private function countGroupedRows(string $table, array $where, ?array $join, array|string|null $column): int
    {
        $where['LIMIT'] = [0, 1];
        $join
            ? $this->db->select($table, $join, $column ?? '1', $where)
            : $this->db->select($table, $column ?? '1', $where);

        $query = $this->db->last();
        $query = substr($query, 0, strrpos($query, 'LIMIT'));

        return (int) $this->db->query("SELECT COUNT(1) FROM ({$query}) groupCount")->fetchColumn();
    }
}
