use leptos::prelude::*;

/// Image with light/dark theme support and click-to-expand fullscreen modal.
///
/// Renders two `<img>` tags (light/dark) with a small "Expand" button. Clicking
/// the image or the button creates a full-viewport overlay directly on `<body>`
/// via `web_sys`, bypassing any CSS stacking context traps (`overflow:hidden`,
/// `transform`, etc.) from ancestor containers.
#[component]
pub fn ImageModal(
    #[prop(into)] src_light: String,
    #[prop(into)] src_dark: String,
    #[prop(into)] alt: String,
    #[prop(into)] expand_label: String,
) -> impl IntoView {
    let _src_light_open = src_light.clone();
    let _src_dark_open = src_dark.clone();
    let _alt_open = alt.clone();

    let open_modal = move || {
        #[cfg(target_arch = "wasm32")]
        {
            open_image_modal(&_src_light_open, &_src_dark_open, &_alt_open);
        }
    };

    let open_modal_clone = open_modal.clone();

    view! {
        <div class="ds-bg ds-rounded-xl border ds-border ds-shadow-lg overflow-hidden p-4">
            <div
                class="cursor-zoom-in"
                on:click=move |_| open_modal()
            >
                <img
                    src=src_light.clone()
                    alt=alt.clone()
                    class="w-full h-auto dark:hidden"
                />
                <img
                    src=src_dark.clone()
                    alt=alt.clone()
                    class="w-full h-auto hidden dark:block"
                />
            </div>
            <button
                class="ds-btn ds-btn-ghost ds-btn-xs mt-2 ds-text-secondary gap-1"
                on:click=move |_| open_modal_clone()
            >
                <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5"/>
                </svg>
                {expand_label}
            </button>
        </div>
    }
}

/// Create a fullscreen overlay on `document.body` with the image.
/// Completely bypasses any CSS stacking context from Leptos component tree.
#[cfg(target_arch = "wasm32")]
fn open_image_modal(src_light: &str, src_dark: &str, alt: &str) {
    use wasm_bindgen::closure::Closure;
    use wasm_bindgen::JsCast;

    let Some(document) = web_sys::window().and_then(|w| w.document()) else {
        return;
    };
    let Some(body) = document.body() else {
        return;
    };

    let is_dark = document
        .document_element()
        .and_then(|el| el.get_attribute("data-theme"))
        .is_some_and(|t| t == "dark");

    let active_src = if is_dark { src_dark } else { src_light };

    let overlay = document.create_element("div").unwrap_or_else(|_| panic!());
    overlay
        .set_attribute(
            "style",
            "position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:\
             center;background:rgba(0,0,0,0.88);cursor:zoom-out;padding:1rem",
        )
        .ok();

    let img = document.create_element("img").unwrap_or_else(|_| panic!());
    img.set_attribute("src", active_src).ok();
    img.set_attribute("alt", alt).ok();
    img.set_attribute("style", "max-width:100%;max-height:100%;object-fit:contain")
        .ok();

    let close_btn = document
        .create_element("button")
        .unwrap_or_else(|_| panic!());
    close_btn
        .set_attribute(
            "style",
            "position:absolute;top:1rem;right:1rem;width:2.5rem;height:2.5rem;border-radius:\
             9999px;display:flex;align-items:center;justify-content:center;background:rgba(255,\
             255,255,0.9);color:#333;border:none;cursor:pointer;font-size:1.5rem;line-height:1",
        )
        .ok();
    close_btn.set_attribute("aria-label", "Close").ok();
    close_btn.set_inner_html("&times;");

    overlay.append_child(&img).ok();
    overlay.append_child(&close_btn).ok();
    body.append_child(&overlay).ok();

    let overlay_ref = overlay.clone();
    let on_click: Closure<dyn Fn()> = Closure::new(move || {
        overlay_ref.remove();
    });

    overlay
        .add_event_listener_with_callback("click", on_click.as_ref().unchecked_ref())
        .ok();

    // Leak the closure — the node is removed on click, making it GC-able.
    on_click.forget();
}
