use crate::ui::Message;
use crate::ui::shared::styles;
use iced::Element;

pub(crate) struct ScrollConfig {
    pub(crate) scroll_offset: f32,
    pub(crate) viewport_height: f32,
    pub(crate) row_height: f32,
    pub(crate) scrollable_id: &'static str,
    pub(crate) on_scroll: fn(iced::widget::scrollable::Viewport) -> Message,
}

pub(crate) fn media_grid<'a>(
    item_count: usize,
    cover_width: f32,
    render_card: impl Fn(usize) -> Element<'a, Message> + 'a,
    scroll: Option<ScrollConfig>,
) -> Element<'a, Message> {
    iced::widget::responsive(move |size| {
        let items_per_row = (size.width / (cover_width + 12.0)).floor().max(1.0) as usize;
        let total_rows = item_count.div_ceil(items_per_row);

        let mut grid = iced::widget::column![]
            .spacing(styles::SPACING_MEDIUM)
            .padding(iced::Padding::ZERO.right(styles::SPACING_MEDIUM));

        let (first_row, last_row) = if let Some(ref sc) = scroll {
            let first_visible = (sc.scroll_offset / sc.row_height).floor() as usize;
            let visible_count = (sc.viewport_height / sc.row_height).ceil() as usize + 2;
            let first = first_visible.saturating_sub(1);
            let last = (first_visible + visible_count).min(total_rows);

            if first > 0 {
                grid = grid.push(
                    iced::widget::container(iced::widget::Space::new())
                        .height(first as f32 * sc.row_height),
                );
            }

            (first, last)
        } else {
            (0, total_rows)
        };

        for row_idx in first_row..last_row {
            let start = row_idx * items_per_row;
            let end = (start + items_per_row).min(item_count);

            let mut row = iced::widget::row![].spacing(styles::SPACING_MEDIUM);
            for idx in start..end {
                row = row.push(
                    iced::widget::container(render_card(idx)).width(iced::Length::FillPortion(1)),
                );
            }
            for _ in (end - start)..items_per_row {
                row = row.push(iced::widget::Space::new().width(iced::Length::FillPortion(1)));
            }
            grid = grid.push(row);
        }

        if let Some(ref sc) = scroll {
            let remaining_rows = total_rows.saturating_sub(last_row);
            if remaining_rows > 0 {
                grid = grid.push(
                    iced::widget::container(iced::widget::Space::new())
                        .height(remaining_rows as f32 * sc.row_height),
                );
            }

            iced::widget::scrollable(grid)
                .id(sc.scrollable_id)
                .on_scroll(sc.on_scroll)
                .width(iced::Length::Fill)
                .height(iced::Length::Fill)
                .into()
        } else {
            grid.into()
        }
    })
    .into()
}
