use crate::components;
use crate::components::header::HeaderItem;
use crate::components::header::HeaderItems;
use crate::components::header::StyledHeader;
use crate::models;
use leptos::Params;
use leptos::prelude::*;
use leptos_router::params::Params;

#[derive(Params, PartialEq, Clone)]
struct RouteParams {
    // Is never None
    wall_uid: Option<models::WallUid>,
}

#[component]
#[tracing::instrument(skip_all)]
pub fn Routes() -> impl IntoView {
    tracing::debug!("Enter");

    let params = leptos_router::hooks::use_params::<RouteParams>();
    let wall_uid = Signal::derive(move || {
        params
            .get()
            .expect("gets wall_uid from URL")
            .wall_uid
            .expect("wall_uid param is never None")
    });

    let wall = crate::resources::wall_by_uid(wall_uid);
    let problems = crate::resources::problems_for_wall(wall_uid);

    let header_items = move || HeaderItems {
        left: vec![HeaderItem {
            text: "← Ascend".to_string(),
            link: Some(format!("/wall/{}", wall_uid.get())),
        }],
        middle: vec![HeaderItem {
            text: "Routes".to_string(),
            link: None,
        }],
        right: vec![],
    };

    let suspend = move || {
        Suspend::new(async move {
            let wall = wall.await;
            let problems = problems.await;

            let v = move || -> Result<_, ServerFnError> {
                let wall = wall.clone()?;
                let problems = problems.clone()?;

                let wall_dimensions = models::WallDimensions {
                    rows: wall.rows,
                    cols: wall.cols,
                };
                let problems_sample = move || problems.iter().take(10).cloned().collect::<Vec<_>>();

                Ok(view! {
                    <div>
                        <For
                            each=problems_sample
                            key=|problem| problem.uid
                            children=move |problem: models::Problem| {
                                view! {
                                    <Problem dim=wall_dimensions problem />
                                    <hr class="my-8 h-px bg-gray-700 border-0" />
                                }
                            }
                        />
                    </div>
                })
            };

            view! { <ErrorBoundary fallback=|_errors| "error">{v}</ErrorBoundary> }
        })
    };

    view! {
        <div class="min-h-screen min-w-screen bg-neutral-950">
            <StyledHeader items=Signal::derive(header_items) />

            <div class="container mx-auto mt-6">
                <Suspense fallback=|| view! { <p>"loading"</p> }>{suspend}</Suspense>
            </div>
        </div>
    }
}

#[component]
#[tracing::instrument(skip_all)]
fn Problem(#[prop(into)] dim: Signal<models::WallDimensions>, #[prop(into)] problem: Signal<models::Problem>) -> impl IntoView {
    view! {
        <div class="flex items-start">
            <div class="flex-none">
                <components::Problem dim problem />
            </div>
            <components::ProblemInfo problem=problem.get() />
        </div>
    }
}
