use log::*;
use model::error::Result;
use sqlx::{FromRow, MySqlPool};

#[derive(Debug, Clone, FromRow)]
pub struct Pager {
    pub page_number: sqlx::types::BigDecimal,
    pub start_version: u64,
    pub end_version: u64,
    pub page_size: i64,
}

impl Pager {
    pub async fn collections_by_version(
        pool: &MySqlPool,
        page_size: u64,
        start: u64,
        end: u64,
    ) -> Result<Vec<Pager>> {
        let pages = sqlx::query_as::<_, Pager>(
            r#"
SELECT
    floor((t.row_num - 1) / ?) + 1 AS page_number,
    min(t.data_version) AS start_version,
    max(t.data_version) AS end_version,
    count(*) AS page_size
FROM (
    SELECT `data_version`, row_number() OVER (ORDER BY `data_version`) AS row_num
    FROM `collections` where `data_version` > ? and `data_version` <= ?
) t
GROUP BY page_number
ORDER BY page_number;"#,
        )
        .bind(page_size)
        .bind(start)
        .bind(end)
        .fetch_all(pool)
        .await?;

        debug!("## Get collection pages {:?}", pages);

        Ok(pages)
    }

    pub async fn documents_by_version(
        pool: &MySqlPool,
        collection_name: &str,
        page_size: u64,
        start: u64,
        end: u64,
    ) -> Result<Vec<Pager>> {
        debug!(
            "Get documents pages from {} withing version [{}, {}]",
            collection_name, start, end
        );
        let pages = sqlx::query_as::<_, Pager>(
            format!(
                r#"
SELECT
    floor((t.row_num - 1) / ?) + 1 AS page_number,
    min(t.version) AS start_version,
    max(t.version) AS end_version,
    count(*) AS page_size
FROM (
    SELECT `version`, row_number() OVER (ORDER BY `version`) AS row_num
    FROM {} where `version` > ? and `version` <= ?
) t
GROUP BY page_number
ORDER BY page_number;"#,
                collection_name
            )
            .as_str(),
        )
        .bind(page_size)
        .bind(start)
        .bind(end)
        .fetch_all(pool)
        .await?;

        debug!("## Get document pages {:?}", pages);

        Ok(pages)
    }
}
