//! Pagination Controls Component
//!
//! Provides configurable pagination controls for content grids
//! with separate implementations for WASM (client-side) and SSR (server-side)

#![allow(dead_code)] // Suppress false positive warnings for Leptos component props

use ::rustelo_core_lib::i18n::create_content_provider;
use leptos::prelude::*;

/// Pagination controls component with conditional WASM/SSR implementations
#[component]
pub fn PaginationControls(
    #[prop(into)] current_page: Signal<u32>,
    #[prop(into)] total_pages: Signal<u32>,
    #[prop(into)] total_items: u32,
    #[prop(into)] items_per_page: Signal<u32>,
    #[prop(into)] content_type: String,
    #[prop(optional)] lang_content: Option<std::collections::HashMap<String, String>>,
    #[prop(optional)] on_page_change: Option<Callback<u32>>,
    #[prop(optional)] on_page_size_change: Option<Callback<u32>>,
    #[prop(default = vec![10, 20, 50])] page_size_options: Vec<u32>,
    #[prop(default = true)] show_page_info: bool,
    #[prop(default = true)] show_page_size_selector: bool,
) -> impl IntoView {
    // Conditional implementation based on environment
    #[cfg(target_arch = "wasm32")]
    {
        view! {
            <PaginationControlsClient
                current_page=current_page
                total_pages=total_pages
                total_items=total_items
                items_per_page=items_per_page
                content_type=content_type
                lang_content=lang_content.clone().unwrap_or_default()
                on_page_change=on_page_change.unwrap_or_else(|| Callback::new(|_| {}))
                on_page_size_change=on_page_size_change.unwrap_or_else(|| Callback::new(|_| {}))
                page_size_options=page_size_options
                show_page_info=show_page_info
                show_page_size_selector=show_page_size_selector
            />
        }
        .into_any()
    }

    #[cfg(not(target_arch = "wasm32"))]
    {
        view! {
            <PaginationControlsSSR
                current_page=current_page
                total_pages=total_pages
                total_items=total_items
                items_per_page=items_per_page
                content_type=content_type
                lang_content=lang_content.unwrap_or_default()
                _on_page_change=on_page_change.unwrap_or_else(|| Callback::new(|_| {}))
                _on_page_size_change=on_page_size_change.unwrap_or_else(|| Callback::new(|_| {}))
                page_size_options=page_size_options
                show_page_info=show_page_info
                show_page_size_selector=show_page_size_selector
            />
        }
        .into_any()
    }
}

/// Client-side pagination implementation with full reactivity
#[component]
#[allow(dead_code)] // False positive: Leptos macro can't detect prop usage in view! macro
fn PaginationControlsClient(
    #[prop(into)] current_page: Signal<u32>,
    #[prop(into)] total_pages: Signal<u32>,
    #[prop(into)] total_items: u32,
    #[prop(into)] items_per_page: Signal<u32>,
    #[prop(into)] content_type: String,
    #[prop(into)] lang_content: std::collections::HashMap<String, String>,
    #[prop(into)] on_page_change: Callback<u32>,
    #[prop(into)] on_page_size_change: Callback<u32>,
    #[prop(default = vec![10, 20, 50])] page_size_options: Vec<u32>,
    #[prop(default = true)] show_page_info: bool,
    #[prop(default = true)] show_page_size_selector: bool,
) -> impl IntoView {
    // Create static values for display (non-reactive in client mode for simplicity)
    let showing_text = create_content_provider(Some(lang_content.clone())).t_with_prefixes(
        "showing",
        &[&content_type, "content"],
        Some("Showing"),
    );
    let of_text = create_content_provider(Some(lang_content.clone())).t_with_prefixes(
        "of",
        &[&content_type, "content"],
        Some("of"),
    );
    let items_text = create_content_provider(Some(lang_content.clone())).t_with_prefixes(
        "items",
        &[&content_type, "content"],
        Some("items"),
    );
    let items_per_page_text = create_content_provider(Some(lang_content.clone())).t_with_prefixes(
        "items-per-page",
        &[&content_type, "content"],
        Some("Items per page:"),
    );

    // Reactive calculations for Client
    let start_item = move || {
        if total_items == 0 {
            0
        } else {
            (current_page.get() - 1) * items_per_page.get() + 1
        }
    };
    let end_item = move || std::cmp::min(current_page.get() * items_per_page.get(), total_items);

    // Don't render if only one page
    let should_render = move || total_pages.get() > 1;

    view! {
        <Show when=should_render fallback=|| ()>
            <div class="pagination-container mt-8 pt-6 border-t border-base-300">
                {if show_page_info {
                    view! {
                            <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-4">
                                <div class="text-sm text-base-content/70">
                                    {
                                        let showing_text = showing_text.clone();
                                        let of_text = of_text.clone();
                                        let items_text = items_text.clone();
                                        move || format!("{} {}-{} {} {} {}",
                                            showing_text,
                                            start_item(),
                                            end_item(),
                                            of_text,
                                            total_items,
                                            items_text
                                        )
                                    }
                                </div>

                            {if show_page_size_selector {
                                view! {
                                    <div class="flex items-center gap-2 text-sm">
                                        <span class="text-base-content/70">
                                            {items_per_page_text.clone()}
                                        </span>
                                        <select
                                            id="pagination-page-size"
                                            name="page-size"
                                            class="ds-select ds-select-bordered ds-select-sm"
                                            on:change=move |ev| {
                                                let value = event_target_value(&ev).parse::<u32>().unwrap_or(items_per_page.get());
                                                on_page_size_change.run(value);
                                            }
                                        >
                                            {page_size_options.iter().map(|&size| {
                                                view! {
                                                    <option
                                                        value={size.to_string()}
                                                        selected={move || size == items_per_page.get()}
                                                    >
                                                        {size.to_string()}
                                                    </option>
                                                }
                                            }).collect_view()}
                                        </select>
                                    </div>
                                }.into_any()
                            } else {
                                view! { <></> }.into_any()
                            }}
                            </div>
                        }.into_any()
                } else {
                    view! { <></> }.into_any()
                }}

                <div class="flex justify-center">
                    <div class="ds-join">
                        // Previous button
                        <button
                            class="ds-join-item ds-btn ds-btn-sm"
                            class:ds-btn-disabled={move || current_page.get() <= 1}
                            disabled={move || current_page.get() <= 1}
                            on:click=move |_| {
                                if current_page.get() > 1 {
                                    on_page_change.run(current_page.get() - 1);
                                }
                            }
                        >
                            "‹"
                        </button>

                        // Page numbers (reactive)
                        {move || {
                            let page_numbers = create_page_numbers(current_page.get(), total_pages.get());
                            page_numbers.into_iter().map(|page_item| {
                                match page_item {
                                    PageItem::Number(page_num) => {
                                        view! {
                                            <button
                                                class="ds-join-item ds-btn ds-btn-sm"
                                                class:ds-btn-active={move || page_num == current_page.get()}
                                                on:click=move |_| {
                                                    on_page_change.run(page_num);
                                                }
                                            >
                                                {page_num.to_string()}
                                            </button>
                                        }.into_any()
                                    },
                                    PageItem::Ellipsis => {
                                        view! {
                                            <span class="ds-join-item ds-btn ds-btn-sm ds-btn-disabled">
                                                "…"
                                            </span>
                                        }.into_any()
                                    }
                                }
                            }).collect_view()
                        }}

                        // Next button
                        <button
                            class="ds-join-item ds-btn ds-btn-sm"
                            class:ds-btn-disabled={move || current_page.get() >= total_pages.get()}
                            disabled={move || current_page.get() >= total_pages.get()}
                            on:click=move |_| {
                                if current_page.get() < total_pages.get() {
                                    on_page_change.run(current_page.get() + 1);
                                }
                            }
                        >
                            "›"
                        </button>
                    </div>
                </div>
            </div>
        </Show>
    }.into_any()
}

/// SSR (Server-side) pagination implementation with static rendering
#[component]
fn PaginationControlsSSR(
    #[prop(into)] current_page: Signal<u32>,
    #[prop(into)] total_pages: Signal<u32>,
    #[prop(into)] total_items: u32,
    #[prop(into)] items_per_page: Signal<u32>,
    #[prop(into)] content_type: String,
    #[prop(into)] lang_content: std::collections::HashMap<String, String>,
    #[prop(into)] _on_page_change: Callback<u32>,
    #[prop(into)] _on_page_size_change: Callback<u32>,
    #[prop(default = vec![10, 20, 50])] page_size_options: Vec<u32>,
    #[prop(default = true)] show_page_info: bool,
    #[prop(default = true)] show_page_size_selector: bool,
) -> impl IntoView {
    let content = create_content_provider(Some(lang_content.clone()));

    // Static calculations for SSR (get values once)
    let current_page_val = current_page.get_untracked();
    let total_pages_val = total_pages.get_untracked();
    let items_per_page_val = items_per_page.get_untracked();

    let start_item = if total_items == 0 {
        0
    } else {
        (current_page_val - 1) * items_per_page_val + 1
    };
    let end_item = std::cmp::min(current_page_val * items_per_page_val, total_items);

    // Don't render if only one page
    if total_pages_val <= 1 {
        return view! { <></> }.into_any();
    }

    let page_numbers = create_page_numbers(current_page_val, total_pages_val);

    view! {
        <div class="pagination-container mt-8 pt-6 border-t border-base-300">
            {if show_page_info {
                view! {
                    <div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-4">
                        <div class="text-sm text-base-content/70">
                            {format!("{} {}-{} {} {} {}",
                                content.t_with_prefixes("showing", &[&content_type, "content"], Some("Showing")),
                                start_item,
                                end_item,
                                content.t_with_prefixes("of", &[&content_type, "content"], Some("of")),
                                total_items,
                                content.t_with_prefixes("items", &[&content_type, "content"], Some("items"))
                            )}
                        </div>

                        {if show_page_size_selector {
                            view! {
                                <div class="flex items-center gap-2 text-sm">
                                    <span class="text-base-content/70">
                                        {content.t_with_prefixes("items-per-page", &[&content_type, "content"], Some("Items per page:"))}
                                    </span>
                                    <select
                                        id="pagination-page-size-static"
                                        name="page-size"
                                        class="ds-select ds-select-bordered ds-select-sm"
                                        disabled=true
                                    >
                                        {page_size_options.iter().map(|&size| {
                                            view! {
                                                <option
                                                    value={size.to_string()}
                                                    selected={size == items_per_page_val}
                                                >
                                                    {size.to_string()}
                                                </option>
                                            }
                                        }).collect_view()}
                                    </select>
                                </div>
                            }.into_any()
                        } else {
                            view! { <></> }.into_any()
                        }}
                    </div>
                }.into_any()
            } else {
                view! { <></> }.into_any()
            }}

            <div class="flex justify-center">
                <div class="ds-join">
                    // Previous button (static)
                    <button
                        class="ds-join-item ds-btn ds-btn-sm"
                        class:ds-btn-disabled={current_page_val <= 1}
                        disabled={current_page_val <= 1}
                    >
                        "‹"
                    </button>

                    // Page numbers (static)
                    {page_numbers.into_iter().map(|page_item| {
                        match page_item {
                            PageItem::Number(page_num) => {
                                view! {
                                    <button
                                        class="ds-join-item ds-btn ds-btn-sm"
                                        class:ds-btn-active={page_num == current_page_val}
                                        disabled={page_num == current_page_val}
                                    >
                                        {page_num.to_string()}
                                    </button>
                                }.into_any()
                            },
                            PageItem::Ellipsis => {
                                view! {
                                    <span class="ds-join-item ds-btn ds-btn-sm ds-btn-disabled">
                                        "…"
                                    </span>
                                }.into_any()
                            }
                        }
                    }).collect_view()}

                    // Next button (static)
                    <button
                        class="ds-join-item ds-btn ds-btn-sm"
                        class:ds-btn-disabled={current_page_val >= total_pages_val}
                        disabled={current_page_val >= total_pages_val}
                    >
                        "›"
                    </button>
                </div>
            </div>
        </div>
    }.into_any()
}

#[derive(Debug, Clone)]
enum PageItem {
    Number(u32),
    Ellipsis,
}

/// Create page numbers with ellipsis logic
fn create_page_numbers(current_page: u32, total_pages: u32) -> Vec<PageItem> {
    let mut pages = Vec::new();

    if total_pages <= 7 {
        // Show all pages if 7 or fewer
        for page in 1..=total_pages {
            pages.push(PageItem::Number(page));
        }
    } else {
        // Always show first page
        pages.push(PageItem::Number(1));

        if current_page <= 4 {
            // Current page is near the beginning
            for page in 2..=5 {
                pages.push(PageItem::Number(page));
            }
            pages.push(PageItem::Ellipsis);
            pages.push(PageItem::Number(total_pages));
        } else if current_page >= total_pages - 3 {
            // Current page is near the end
            pages.push(PageItem::Ellipsis);
            for page in (total_pages - 4)..=total_pages {
                pages.push(PageItem::Number(page));
            }
        } else {
            // Current page is in the middle
            pages.push(PageItem::Ellipsis);
            for page in (current_page - 1)..=(current_page + 1) {
                pages.push(PageItem::Number(page));
            }
            pages.push(PageItem::Ellipsis);
            pages.push(PageItem::Number(total_pages));
        }
    }

    pages
}
