use serde::{Deserialize, Serialize};

#[cfg(feature = "openapi")]
use utoipa::ToSchema;

#[derive(Debug, Clone, Copy, Deserialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema, utoipa::IntoParams))]
pub struct PageRequest {
    #[serde(default = "default_page")]
    pub page: u32, // 1'den başlar

    #[serde(default = "default_size")]
    pub size: u32,
}

fn default_page() -> u32 {
    1
}
fn default_size() -> u32 {
    10
}

impl Default for PageRequest {
    fn default() -> Self {
        Self {
            page: default_page(),
            size: default_size(),
        }
    }
}

impl PageRequest {
    pub fn normalized(self, max_page_size: u32) -> Self {
        let size = self.size.clamp(1, max_page_size.max(1));
        let page = self.page.max(1);
        Self { page, size }
    }

    pub fn offset_limit(self) -> (u32, u32) {
        let page = self.page.max(1);
        let size = self.size.max(1);
        let offset = (page - 1).saturating_mul(size);
        (offset, size)
    }
}

#[derive(Debug, Clone, Serialize)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
pub struct Paged<T> {
    pub items: Vec<T>,
    pub total_items: u64,
    pub page: u32,
    pub size: u32,
    pub total_pages: u32,
}

impl<T> Paged<T> {
    pub fn new(items: Vec<T>, total_items: u64, page: u32, size: u32) -> Self {
        let size = size.max(1);
        let total_pages = if total_items == 0 {
            0
        } else {
            ((total_items + size as u64 - 1) / size as u64) as u32
        };

        Self {
            items,
            total_items,
            page: page.max(1),
            size,
            total_pages,
        }
    }
}
