//! Overlay components for prop editing in scene viewer.
//!
//! Contains ScaleOverlay and MoveOverlay components used when
//! moderators edit prop scale or position.

use leptos::prelude::*;
use uuid::Uuid;

use chattyness_db::models::LooseProp;

use super::super::settings::{BASE_AVATAR_SCALE, BASE_PROP_SCALE};
#[cfg(feature = "hydrate")]
use super::super::canvas_utils::normalize_asset_path;

/// Overlay shown when editing a prop's scale.
///
/// Allows dragging from the prop center to adjust scale.
#[component]
pub fn ScaleOverlay(
    #[prop(into)] active: Signal<bool>,
    #[prop(into)] prop_id: Signal<Option<Uuid>>,
    #[prop(into)] preview_scale: RwSignal<f32>,
    #[prop(into)] prop_center: Signal<(f64, f64)>,
    #[prop(into)] loose_props: Signal<Vec<LooseProp>>,
    #[prop(into)] prop_size: Signal<f64>,
    #[prop(optional)] on_apply: Option<Callback<(Uuid, f32)>>,
    #[prop(optional)] on_cancel: Option<Callback<()>>,
) -> impl IntoView {
    let (_center_x, _center_y) = prop_center.get_untracked();

    view! {
        <Show when=move || active.get()>
            {move || {
                let current_prop_id = prop_id.get();
                let current_preview_scale = preview_scale.get();
                let (center_x, center_y) = prop_center.get();

                // Find the prop to get its dimensions
                let prop_data = current_prop_id.and_then(|id| {
                    loose_props.get().iter().find(|p| p.id == id).cloned()
                });

                view! {
                    <div
                        class="fixed inset-0 z-50 cursor-crosshair"
                        style="background: rgba(0,0,0,0.3);"
                        on:mousemove=move |ev| {
                            #[cfg(feature = "hydrate")]
                            {
                                use wasm_bindgen::JsCast;
                                let ev: web_sys::MouseEvent = ev.dyn_into().unwrap();
                                let mouse_x = ev.client_x() as f64;
                                let mouse_y = ev.client_y() as f64;
                                let (cx, cy) = prop_center.get();
                                let dx = mouse_x - cx;
                                let dy = mouse_y - cy;
                                let distance = (dx * dx + dy * dy).sqrt();
                                // Scale formula: distance / 40 gives 1x at 40px
                                let new_scale = (distance / 40.0).clamp(0.1, 10.0) as f32;
                                preview_scale.set(new_scale);
                            }
                            #[cfg(not(feature = "hydrate"))]
                            let _ = ev;
                        }
                        on:mouseup=move |ev| {
                            #[cfg(feature = "hydrate")]
                            {
                                if let (Some(pid), Some(ref callback)) = (prop_id.get(), on_apply.as_ref()) {
                                    let final_scale = preview_scale.get();
                                    callback.run((pid, final_scale));
                                }
                                if let Some(ref callback) = on_cancel {
                                    callback.run(());
                                }
                            }
                            #[cfg(not(feature = "hydrate"))]
                            let _ = ev;
                        }
                        on:keydown=move |ev| {
                            #[cfg(feature = "hydrate")]
                            {
                                use wasm_bindgen::JsCast;
                                let ev: web_sys::KeyboardEvent = ev.dyn_into().unwrap();
                                if ev.key() == "Escape" {
                                    ev.prevent_default();
                                    if let Some(ref callback) = on_cancel {
                                        callback.run(());
                                    }
                                }
                            }
                            #[cfg(not(feature = "hydrate"))]
                            let _ = ev;
                        }
                        tabindex="0"
                    >
                        // Visual feedback: dashed border around prop
                        {move || {
                            if let Some(ref _prop) = prop_data {
                                let base_size = prop_size.get();
                                let prop_scale_ratio = BASE_PROP_SCALE / BASE_AVATAR_SCALE;
                                let preview_prop_size = base_size * prop_scale_ratio * current_preview_scale as f64;
                                let half_size = preview_prop_size / 2.0;
                                view! {
                                    <div
                                        class="absolute pointer-events-none"
                                        style=format!(
                                            "left: {}px; top: {}px; width: {}px; height: {}px; \
                                             border: 2px dashed #fbbf24; \
                                             transform: translate(-50%, -50%); \
                                             box-sizing: border-box;",
                                            center_x, center_y, preview_prop_size, preview_prop_size
                                        )
                                    />
                                    // Scale indicator
                                    <div
                                        class="absolute bg-gray-900/90 text-yellow-400 px-2 py-1 rounded text-sm font-mono pointer-events-none"
                                        style=format!(
                                            "left: {}px; top: {}px; transform: translate(-50%, 8px);",
                                            center_x, center_y + half_size
                                        )
                                    >
                                        {format!("{:.2}x", current_preview_scale)}
                                    </div>
                                }.into_any()
                            } else {
                                ().into_any()
                            }
                        }}
                        // Instructions
                        <div class="absolute bottom-4 left-1/2 -translate-x-1/2 bg-gray-900/90 text-white px-4 py-2 rounded text-sm">
                            "Drag to resize • Release to apply • Escape to cancel"
                        </div>
                    </div>
                }
            }}
        </Show>
    }
}

/// Overlay shown when moving a prop to a new position.
#[component]
pub fn MoveOverlay(
    #[prop(into)] active: Signal<bool>,
    #[prop(into)] prop_id: Signal<Option<Uuid>>,
    #[prop(into)] preview_position: RwSignal<(f64, f64)>,
    #[prop(into)] prop_scale: Signal<f32>,
    #[prop(into)] loose_props: Signal<Vec<LooseProp>>,
    #[prop(into)] prop_size: Signal<f64>,
    #[prop(into)] scale_x: Signal<f64>,
    #[prop(into)] scale_y: Signal<f64>,
    #[prop(into)] offset_x: Signal<f64>,
    #[prop(into)] offset_y: Signal<f64>,
    #[prop(optional)] on_apply: Option<Callback<(Uuid, f64, f64)>>,
    #[prop(optional)] on_cancel: Option<Callback<()>>,
) -> impl IntoView {
    view! {
        <Show when=move || active.get()>
            {move || {
                let current_prop_id = prop_id.get();
                let (_preview_x, _preview_y) = preview_position.get();
                let current_prop_scale = prop_scale.get();

                // Find the prop to get its asset path
                let prop_data = current_prop_id.and_then(|id| {
                    loose_props.get().iter().find(|p| p.id == id).cloned()
                });

                // Calculate ghost size
                let base_size = prop_size.get();
                let prop_scale_ratio = BASE_PROP_SCALE / BASE_AVATAR_SCALE;
                let ghost_size = base_size * prop_scale_ratio * current_prop_scale as f64;

                view! {
                    <div
                        class="fixed inset-0 z-50 cursor-crosshair"
                        style="background: rgba(0,0,0,0.3);"
                        on:mousemove=move |ev| {
                            #[cfg(feature = "hydrate")]
                            {
                                use wasm_bindgen::JsCast;
                                let ev: web_sys::MouseEvent = ev.dyn_into().unwrap();
                                let mouse_x = ev.client_x() as f64;
                                let mouse_y = ev.client_y() as f64;

                                // Get scene viewer's position
                                let document = web_sys::window().unwrap().document().unwrap();
                                if let Some(viewer) = document.query_selector(".scene-viewer-container").ok().flatten() {
                                    let rect = viewer.get_bounding_client_rect();
                                    let viewer_x = mouse_x - rect.left();
                                    let viewer_y = mouse_y - rect.top();

                                    let sx = scale_x.get();
                                    let sy = scale_y.get();
                                    let ox = offset_x.get();
                                    let oy = offset_y.get();

                                    if sx > 0.0 && sy > 0.0 {
                                        let scene_x = (viewer_x - ox) / sx;
                                        let scene_y = (viewer_y - oy) / sy;
                                        preview_position.set((scene_x, scene_y));
                                    }
                                }
                            }
                            #[cfg(not(feature = "hydrate"))]
                            let _ = ev;
                        }
                        on:click=move |ev| {
                            #[cfg(feature = "hydrate")]
                            {
                                if let (Some(pid), Some(ref callback)) = (prop_id.get(), on_apply.as_ref()) {
                                    let (final_x, final_y) = preview_position.get();
                                    callback.run((pid, final_x, final_y));
                                }
                                if let Some(ref callback) = on_cancel {
                                    callback.run(());
                                }
                            }
                            #[cfg(not(feature = "hydrate"))]
                            let _ = ev;
                        }
                        on:keydown=move |ev| {
                            #[cfg(feature = "hydrate")]
                            {
                                use wasm_bindgen::JsCast;
                                let ev: web_sys::KeyboardEvent = ev.dyn_into().unwrap();
                                if ev.key() == "Escape" {
                                    ev.prevent_default();
                                    if let Some(ref callback) = on_cancel {
                                        callback.run(());
                                    }
                                }
                            }
                            #[cfg(not(feature = "hydrate"))]
                            let _ = ev;
                        }
                        tabindex="0"
                    >
                        // Ghost prop at cursor position
                        {move || {
                            #[cfg(feature = "hydrate")]
                            {
                                if let Some(ref prop) = prop_data {
                                    let (preview_x, preview_y) = preview_position.get();
                                    let sx = scale_x.get();
                                    let sy = scale_y.get();
                                    let ox = offset_x.get();
                                    let oy = offset_y.get();

                                    // Get scene viewer position in viewport
                                    let document = web_sys::window().unwrap().document().unwrap();
                                    let viewer_offset = document
                                        .query_selector(".scene-viewer-container")
                                        .ok()
                                        .flatten()
                                        .map(|v| {
                                            let rect = v.get_bounding_client_rect();
                                            (rect.left(), rect.top())
                                        })
                                        .unwrap_or((0.0, 0.0));

                                    // Convert scene coords to viewport coords
                                    let viewer_x = preview_x * sx + ox;
                                    let viewer_y = preview_y * sy + oy;
                                    let viewport_x = viewer_x + viewer_offset.0;
                                    let viewport_y = viewer_y + viewer_offset.1;

                                    let normalized_path = normalize_asset_path(&prop.prop_asset_path);

                                    view! {
                                        <div
                                            class="absolute pointer-events-none"
                                            style=format!(
                                                "left: {}px; top: {}px; width: {}px; height: {}px; \
                                                 transform: translate(-50%, -50%); \
                                                 border: 2px dashed #10b981; \
                                                 background: rgba(16, 185, 129, 0.2); \
                                                 box-sizing: border-box;",
                                                viewport_x, viewport_y, ghost_size, ghost_size
                                            )
                                        >
                                            <img
                                                src=normalized_path
                                                class="w-full h-full object-contain opacity-50"
                                                style="pointer-events: none;"
                                            />
                                        </div>
                                    }.into_any()
                                } else {
                                    ().into_any()
                                }
                            }
                            #[cfg(not(feature = "hydrate"))]
                            {
                                ().into_any()
                            }
                        }}
                        // Instructions
                        <div class="absolute bottom-4 left-1/2 -translate-x-1/2 bg-gray-900/90 text-white px-4 py-2 rounded text-sm">
                            "Click to place • Escape to cancel"
                        </div>
                    </div>
                }
            }}
        </Show>
    }
}
