//! Client-side Page Transition Components
//!
//! Reactive implementation of page transition components for client-side
//! rendering.

use std::time::Duration;

use leptos::prelude::*;

// Import the unified TransitionStyle instead of defining a duplicate
use super::unified::TransitionStyle;

impl TransitionStyle {
    fn out_class(&self) -> &'static str {
        match self {
            Self::Fade => "fade-out",
            Self::Slide => "slide-out",
            Self::Scale => "scale-out",
        }
    }

    fn in_class(&self) -> &'static str {
        match self {
            Self::Fade => "fade-in",
            Self::Slide => "slide-in",
            Self::Scale => "scale-in",
        }
    }
}

/// Client-side hydration-safe page transition wrapper component
#[component]
pub fn PageTransition(
    /// Signal that triggers the transition (usually the route path)
    trigger: ReadSignal<String>,
    /// Children to render with transitions
    children: Children,
    /// Transition style to use
    #[prop(default = TransitionStyle::Fade)]
    style: TransitionStyle,
    /// Duration of the transition in milliseconds
    #[prop(default = 300)]
    duration_ms: u64,
) -> impl IntoView {
    // Start with base class for hydration safety
    let (transition_class, set_transition_class) = signal(String::from("page-content"));
    let (is_hydrated, _set_is_hydrated) = signal(false);

    // Mark as hydrated after initial render to avoid hydration issues
    #[cfg(target_arch = "wasm32")]
    Effect::new(move |_| {
        if !is_hydrated.get() {
            // Small delay to ensure hydration is complete
            set_timeout(
                move || {
                    _set_is_hydrated.set(true);
                },
                Duration::from_millis(10),
            );
        }
    });

    // Create effect to handle transitions on path change - only after hydration
    Effect::new(move |prev_path: Option<String>| {
        let current_path = trigger.get();

        // Only transition if hydrated and path actually changed
        if is_hydrated.get() {
            if let Some(prev) = prev_path {
                if prev != current_path {
                    // Start fade out
                    set_transition_class.set(format!("page-content {}", style.out_class()));

                    // After a short delay, start fade in
                    set_timeout(
                        move || {
                            set_transition_class.set(format!("page-content {}", style.in_class()));
                        },
                        Duration::from_millis(150),
                    );

                    // Clear transition state after animation completes
                    set_timeout(
                        move || {
                            set_transition_class.set(String::from("page-content"));
                        },
                        Duration::from_millis(duration_ms),
                    );
                }
            }
        }

        current_path
    });

    view! {
        <div class="page-transition-wrapper">
            <div class=move || transition_class.get()>
                {children()}
            </div>
        </div>
    }
}

/// Client-side simpler page transition that just uses CSS classes
#[component]
pub fn SimplePageTransition(
    /// Children to render with transitions
    children: Children,
    /// Additional CSS classes
    #[prop(default = String::new())]
    class: String,
) -> impl IntoView {
    view! {
        <div class=format!("page-content fade-in {}", class)>
            {children()}
        </div>
    }
}
