//! Avatar thumbnail component for rendering avatar previews.
//!
//! A simplified canvas-based component for rendering avatars in the
//! avatar store grid. Uses the same layer compositing as the main
//! avatar renderer but at thumbnail size.

use leptos::prelude::*;
use leptos::web_sys;

/// Avatar thumbnail component for the avatar store.
///
/// Renders a small preview of an avatar using canvas compositing.
/// Takes layer paths directly as props.
///
/// Props:
/// - `skin_layer`: Asset paths for skin layer positions 0-8
/// - `clothes_layer`: Asset paths for clothes layer positions 0-8
/// - `accessories_layer`: Asset paths for accessories layer positions 0-8
/// - `emotion_layer`: Asset paths for emotion layer positions 0-8
/// - `size`: Optional canvas size in pixels (default: 80)
#[component]
pub fn AvatarThumbnail(
    #[prop(into)] skin_layer: Signal<[Option<String>; 9]>,
    #[prop(into)] clothes_layer: Signal<[Option<String>; 9]>,
    #[prop(into)] accessories_layer: Signal<[Option<String>; 9]>,
    #[prop(into)] emotion_layer: Signal<[Option<String>; 9]>,
    #[prop(default = 80)] size: u32,
) -> impl IntoView {
    let canvas_ref = NodeRef::<leptos::html::Canvas>::new();
    let cell_size = size / 3;

    #[cfg(feature = "hydrate")]
    {
        use std::cell::RefCell;
        use std::collections::HashMap;
        use std::rc::Rc;
        use wasm_bindgen::JsCast;
        use wasm_bindgen::closure::Closure;

        use crate::utils::normalize_asset_path;

        // Image cache for this thumbnail
        let image_cache: Rc<RefCell<HashMap<String, web_sys::HtmlImageElement>>> =
            Rc::new(RefCell::new(HashMap::new()));

        // Redraw trigger - incremented when images load
        let (redraw_trigger, set_redraw_trigger) = signal(0u32);

        Effect::new(move |_| {
            // Subscribe to redraw trigger
            let _ = redraw_trigger.get();

            let Some(canvas) = canvas_ref.get() else {
                return;
            };

            let skin = skin_layer.get();
            let clothes = clothes_layer.get();
            let accessories = accessories_layer.get();
            let emotion = emotion_layer.get();

            let canvas_el: &web_sys::HtmlCanvasElement = &canvas;
            canvas_el.set_width(size);
            canvas_el.set_height(size);

            let Ok(Some(ctx)) = canvas_el.get_context("2d") else {
                return;
            };
            let ctx: web_sys::CanvasRenderingContext2d = ctx.dyn_into().unwrap();

            // Clear canvas
            ctx.clear_rect(0.0, 0.0, size as f64, size as f64);

            // Draw background
            ctx.set_fill_style_str("#374151");
            ctx.fill_rect(0.0, 0.0, size as f64, size as f64);

            // Helper to load and draw an image at a grid position
            let draw_at_position =
                |path: &str,
                 pos: usize,
                 cache: &Rc<RefCell<HashMap<String, web_sys::HtmlImageElement>>>,
                 ctx: &web_sys::CanvasRenderingContext2d| {
                    let normalized_path = normalize_asset_path(path);
                    let mut cache_borrow = cache.borrow_mut();
                    let row = pos / 3;
                    let col = pos % 3;
                    let x = (col * cell_size as usize) as f64;
                    let y = (row * cell_size as usize) as f64;
                    let sz = cell_size as f64;

                    if let Some(img) = cache_borrow.get(&normalized_path) {
                        if img.complete() && img.natural_width() > 0 {
                            let _ = ctx.draw_image_with_html_image_element_and_dw_and_dh(
                                img, x, y, sz, sz,
                            );
                        }
                    } else {
                        let img = web_sys::HtmlImageElement::new().unwrap();
                        let trigger = set_redraw_trigger;
                        let onload = Closure::once(Box::new(move || {
                            trigger.update(|v| *v += 1);
                        }) as Box<dyn FnOnce()>);
                        img.set_onload(Some(onload.as_ref().unchecked_ref()));
                        onload.forget();
                        img.set_src(&normalized_path);
                        cache_borrow.insert(normalized_path, img);
                    }
                };

            // Draw layers in order: skin -> clothes -> accessories -> emotion
            for (pos, path) in skin.iter().enumerate() {
                if let Some(p) = path {
                    draw_at_position(p, pos, &image_cache, &ctx);
                }
            }

            for (pos, path) in clothes.iter().enumerate() {
                if let Some(p) = path {
                    draw_at_position(p, pos, &image_cache, &ctx);
                }
            }

            for (pos, path) in accessories.iter().enumerate() {
                if let Some(p) = path {
                    draw_at_position(p, pos, &image_cache, &ctx);
                }
            }

            for (pos, path) in emotion.iter().enumerate() {
                if let Some(p) = path {
                    draw_at_position(p, pos, &image_cache, &ctx);
                }
            }
        });
    }

    view! {
        <canvas
            node_ref=canvas_ref
            style=format!("width: {}px; height: {}px;", size, size)
            class="rounded"
        />
    }
}
