//! Aspirational RUIN app API for async resources and effects.
//!
//! Intentionally non-compiling; this is a design sketch.

use ruin::prelude::*;

#[ruin_runtime::async_main]
async fn main() -> ruin::Result<()> {
    App::new()
        .window(Window::new().title("RUIN Issue Dashboard").size(1240.0, 820.0))
        .mount::<IssueDashboard>()
        .run()
        .await
}

#[component]
fn IssueDashboard() -> impl View {
    let repo = use_signal(|| "wtemple/ruin".to_string());
    let selected_issue = use_signal(|| None::<u64>);

    let issues = use_resource(move || {
        let repo = repo.get();
        async move { github::list_issues(&repo).await }
    });

    let details = use_resource(move || {
        let repo = repo.get();
        let issue_id = selected_issue.get();
        async move {
            let issue_id = issue_id?;
            github::issue_details(&repo, issue_id).await.ok()
        }
    });

    use_effect(move || {
        tracing::info!(
            repo = %repo.get(),
            selected_issue = ?selected_issue.get(),
            "dashboard dependencies changed"
        );
    });

    view! {
        row(fill = true, gap = 20, padding = 20) {
            block(width = 360, gap = 12) {
                text(role = TextRole::Heading(1), size = 28, weight = FontWeight::Semibold) {
                    "Issues"
                }

                text_input(value = repo, placeholder = "owner/repo") {}

                suspense(fallback = || view! { ProgressSpinner(label = "Loading issues...") {} }) {
                    match issues.read() {
                        Ok(items) => view! {
                            list(gap = 8) {
                                for issue in items keyed by issue.id {
                                    button(
                                        kind = if selected_issue.get() == Some(issue.id) {
                                            ButtonKind::Primary
                                        } else {
                                            ButtonKind::Secondary
                                        },
                                        on_press = move |_| selected_issue.set(Some(issue.id)),
                                    ) {
                                        issue.title
                                    }
                                }
                            }
                        },
                        Err(error) => view! {
                            ErrorPanel(
                                title = "Failed to load issues",
                                detail = error.to_string(),
                            ) {}
                        },
                    }
                }
            }

            block(fill = true, gap = 16) {
                text(role = TextRole::Heading(2), size = 24, weight = FontWeight::Semibold) {
                    "Details"
                }

                match details.read() {
                    Pending => view! { ProgressSpinner(label = "Loading issue details...") {} },
                    Ready(Some(issue)) => view! {
                        column(gap = 12) {
                            text(role = TextRole::Heading(3), size = 22, weight = FontWeight::Semibold) {
                                issue.title
                            }
                            Markdown(source = issue.body) {}
                        }
                    },
                    Ready(None) => view! {
                        EmptyState(title = "Pick an issue") {
                            "The detail panel should track the current selection and re-run only \
                             the async work that actually depends on it."
                        }
                    },
                }
            }
        }
    }
}
