use leptos::prelude::*;

#[cfg(not(target_arch = "wasm32"))]
use super::GRAPH_JSON;

/// Full-page knowledge graph view.
///
/// `node_id`: when provided, the graph centers on that node (ego view).
#[component]
pub fn GraphView(
    #[prop(optional)] node_id: Option<String>,
    #[prop(default = String::from("light"))] theme: String,
) -> impl IntoView {
    #[cfg(not(target_arch = "wasm32"))]
    return view! { <GraphViewInner node_id=node_id theme=theme /> };

    #[cfg(target_arch = "wasm32")]
    return view! { <GraphViewClient node_id=node_id theme=theme /> };
}

// ── SSR ───────────────────────────────────────────────────────────────────────

#[cfg(not(target_arch = "wasm32"))]
#[component]
fn GraphViewInner(
    node_id: Option<String>,
    theme:   String,
) -> impl IntoView {
    let focus           = node_id.unwrap_or_default();
    let graph_json_safe = GRAPH_JSON.replace("</", "\\/");

    view! {
        <div class="content-graph-page w-full">
            <script
                type="application/json"
                id="content-graph-data"
                inner_html=graph_json_safe
            />
            <div
                id="content-graph-cyto"
                data-focus=focus
                data-theme=theme
                class="w-full h-[600px] ds-bg-page ds-border ds-rounded-lg overflow-hidden"
                aria-label="Knowledge graph visualisation"
                role="img"
            >
                <noscript>
                    <p class="p-4 ds-caption text-center">
                        "Interactive graph requires JavaScript."
                    </p>
                </noscript>
            </div>
        </div>
    }
}

// ── WASM ──────────────────────────────────────────────────────────────────────

#[cfg(target_arch = "wasm32")]
#[component]
fn GraphViewClient(
    node_id: Option<String>,
    theme:   String,
) -> impl IntoView {
    let focus       = node_id.unwrap_or_default();
    let focus_clone = focus.clone();
    let theme_clone = theme.clone();

    Effect::new(move |_| {
        let focus = focus_clone.clone();
        let theme = theme_clone.clone();
        call_cytoscape_render("content-graph-cyto", &focus, &theme);
    });

    on_cleanup(move || {
        call_cytoscape_destroy("content-graph-cyto");
    });

    view! {
        <div class="content-graph-page w-full">
            <div
                id="content-graph-cyto"
                data-focus=focus
                data-theme=theme
                class="w-full h-[600px] ds-bg-page ds-border ds-rounded-lg overflow-hidden"
                aria-label="Knowledge graph visualisation"
                role="img"
            />
        </div>
    }
}

// ── JS interop ────────────────────────────────────────────────────────────────

#[cfg(target_arch = "wasm32")]
fn call_cytoscape_render(container_id: &str, focus: &str, theme: &str) {
    use wasm_bindgen::{JsCast, JsValue};

    let Some(window) = web_sys::window() else { return };
    let Ok(content_graph) = js_sys::Reflect::get(&window, &JsValue::from_str("ContentGraph"))
        else { return };
    let Ok(render_fn) = js_sys::Reflect::get(&content_graph, &JsValue::from_str("render"))
        else { return };
    let render_fn: js_sys::Function = match render_fn.dyn_into() {
        Ok(f) => f,
        Err(_) => return,
    };
    let _ = render_fn.call3(
        &content_graph,
        &JsValue::from_str(container_id),
        &JsValue::from_str(focus),
        &JsValue::from_str(theme),
    );
}

#[cfg(target_arch = "wasm32")]
fn call_cytoscape_destroy(container_id: &str) {
    use wasm_bindgen::{JsCast, JsValue};

    let Some(window) = web_sys::window() else { return };
    let Ok(content_graph) = js_sys::Reflect::get(&window, &JsValue::from_str("ContentGraph"))
        else { return };
    let Ok(destroy_fn) = js_sys::Reflect::get(&content_graph, &JsValue::from_str("destroy"))
        else { return };
    let destroy_fn: js_sys::Function = match destroy_fn.dyn_into() {
        Ok(f) => f,
        Err(_) => return,
    };
    let _ = destroy_fn.call1(&content_graph, &JsValue::from_str(container_id));
}
