use leptos::prelude::*;
#[cfg(target_arch = "wasm32")]
use rustelo_core_lib::i18n::use_unified_i18n;

#[cfg(target_arch = "wasm32")]
use super::manage_modal::CookieManageModal;

#[cfg(target_arch = "wasm32")]
const CONSENT_KEY: &str = "cookie_consent";

/// Cookie consent banner. Renders nothing in SSR — only active in WASM.
#[component]
pub fn CookieBanner(
    #[prop(default = "/privacy".to_string())] policy_page: String,
    /// "modal" shows the category picker inline; anything else navigates to
    /// policy_page.
    #[prop(default = "page".to_string())]
    detail_mode: String,
) -> impl IntoView {
    #[cfg(target_arch = "wasm32")]
    {
        let i18n = use_unified_i18n();
        let banner_text = i18n.t("cookies-banner-text");
        let policy_link = i18n.t("cookies-policy-link");
        let policy_suffix = i18n.t("cookies-policy-suffix");
        let manage_label = i18n.t("cookies-manage");
        let reject_label = i18n.t("cookies-reject");
        let accept_label = i18n.t("cookies-accept-all");

        let show = RwSignal::new(false);
        let show_manage = RwSignal::new(false);

        // Read localStorage on mount to decide whether to show the banner
        Effect::new(move |_| {
            if let Some(storage) = local_storage() {
                let already_set = storage.get_item(CONSENT_KEY).ok().flatten().is_some();
                show.set(!already_set);
            }
        });

        // Lock body scroll while banner (or manage modal) is visible
        Effect::new(move |_| {
            let visible = show.get() || show_manage.get();
            if let Some(body) = web_sys::window()
                .and_then(|w| w.document())
                .and_then(|d| d.body())
            {
                let _ = if visible {
                    body.style().set_property("overflow", "hidden")
                } else {
                    body.style().remove_property("overflow").map(|_| ())
                };
            }
        });

        // Wrap as Callback (Copy via StoredValue) so they can be captured by Fn
        // children closures
        let write_consent_essential = Callback::<leptos::ev::MouseEvent>::new(move |_| {
            if let Some(storage) = local_storage() {
                let _ = storage.set_item(CONSENT_KEY, "essential");
            }
            show.set(false);
        });
        let write_consent_all = Callback::<leptos::ev::MouseEvent>::new(move |_| {
            if let Some(storage) = local_storage() {
                let _ = storage.set_item(CONSENT_KEY, "all");
            }
            show.set(false);
        });
        let on_manage = Callback::<leptos::ev::MouseEvent>::new({
            let policy = policy_page.clone();
            let mode = detail_mode.clone();
            move |_| {
                if mode == "modal" {
                    show_manage.set(true);
                } else if let Some(set_path) = use_context::<WriteSignal<String>>() {
                    set_path.set(policy.clone());
                }
            }
        });

        let policy_href = policy_page.clone();

        view! {
            <Show when=move || show.get()>
                // Blocking overlay — prevents any interaction with page content
                // until the user makes a cookie choice. Not dismissible by click.
                <div class="fixed inset-0 z-100 bg-black opacity-75" />
                // Banner panel — fully opaque, above the overlay
                <div class="fixed bottom-0 left-0 right-0 z-120 bg-base-100 border-t-2 border-base-300 shadow-2xl
                    px-6 py-5 flex flex-col sm:flex-row items-start sm:items-center gap-4">
                    <p class="text-sm flex-1 dark:color-white">
                        {banner_text.clone()}
                        " "
                        <a class="underline" href=policy_href.clone()>{policy_link.clone()}</a>
                        " "
                        {policy_suffix.clone()}
                    </p>
                    <div class="flex items-center gap-2 shrink-0 dark:color-white">
                        <button
                            class="btn btn-ghost btn-sm rounded-full"
                            on:click=move |e| on_manage.run(e)
                        >
                            {manage_label.clone()}
                        </button>
                        <button
                            class="btn btn-ghost btn-sm rounded-full dark:color-white"
                            on:click=move |e| write_consent_essential.run(e)
                        >
                            {reject_label.clone()}
                        </button>
                        <button
                            class="btn btn-neutral btn-sm rounded-full dark:color-white"
                            on:click=move |e| write_consent_all.run(e)
                        >
                            {accept_label.clone()}
                        </button>
                    </div>
                </div>
            </Show>
            <Show when=move || show_manage.get()>
                <CookieManageModal
                    on_save=Callback::new(move |prefs: String| {
                        if let Some(storage) = local_storage() {
                            let _ = storage.set_item(CONSENT_KEY, &prefs);
                        }
                        show.set(false);
                        show_manage.set(false);
                    })
                    on_close=Callback::new(move |_: ()| show_manage.set(false))
                />
            </Show>
        }
        .into_any()
    }

    // SSR: emit TWO DynChild pairs to match WASM's two <Show> components
    // (banner Show + manage modal Show).  Each Show with when=false emits one
    // reactive-node marker; the sequential hydration counter must match exactly.
    #[cfg(not(target_arch = "wasm32"))]
    {
        let _ = (policy_page, detail_mode);
        view! { {move || ()} {move || ()} }.into_any()
    }
}

#[cfg(target_arch = "wasm32")]
fn local_storage() -> Option<web_sys::Storage> {
    web_sys::window()?.local_storage().ok()?
}
