//! Modal components with WCAG 2.2 AA accessibility.

use leptos::prelude::*;

use crate::utils::use_escape_key;

// ============================================================================
// Base Modal Component
// ============================================================================

/// Base modal component that handles common modal patterns.
///
/// Provides:
/// - Backdrop with blur effect
/// - Escape key to close
/// - Click outside to close
/// - Accessible ARIA attributes
/// - Close button in header
///
/// # Example
///
/// ```ignore
/// <Modal
///     open=open_signal
///     on_close=on_close_callback
///     title="My Modal"
///     title_id="my-modal-title"
/// >
///     <p>"Modal content here"</p>
/// </Modal>
/// ```
#[component]
pub fn Modal(
    #[prop(into)] open: Signal<bool>,
    on_close: Callback<()>,
    title: &'static str,
    /// Unique ID for the title element (for aria-labelledby).
    title_id: &'static str,
    /// Maximum width class (e.g., "max-w-md", "max-w-2xl"). Defaults to "max-w-md".
    #[prop(default = "max-w-md")]
    max_width: &'static str,
    /// Whether to show the close button. Defaults to true.
    #[prop(default = true)]
    show_close_button: bool,
    /// Optional extra classes for the modal container.
    #[prop(optional)]
    class: Option<&'static str>,
    children: Children,
) -> impl IntoView {
    // Handle escape key
    use_escape_key(open, on_close.clone());

    let on_close_backdrop = on_close.clone();
    let on_close_button = on_close.clone();

    let container_class = format!(
        "relative bg-gray-800 rounded-lg shadow-2xl {} w-full mx-4 p-6 border border-gray-700 {}",
        max_width,
        class.unwrap_or("")
    );

    // Render children once
    let content = children();

    // Use CSS-based visibility instead of Show for better children handling
    let outer_class = move || {
        if open.get() {
            "fixed inset-0 z-50 flex items-center justify-center"
        } else {
            "hidden"
        }
    };

    view! {
        <div
            class=outer_class
            role="dialog"
            aria-modal="true"
            aria-labelledby=title_id
            aria-hidden=move || (!open.get()).to_string()
        >
            // Backdrop
            <div
                class="absolute inset-0 bg-black/70 backdrop-blur-sm"
                on:click=move |_| on_close_backdrop.run(())
                aria-hidden="true"
            />

            // Modal content
            <div class=container_class>
                // Header with title and close button
                <div class="flex items-center justify-between mb-4">
                    <h2 id=title_id class="text-xl font-bold text-white">
                        {title}
                    </h2>
                    {show_close_button.then(|| view! {
                        <button
                            type="button"
                            class="text-gray-400 hover:text-white transition-colors"
                            on:click=move |_| on_close_button.run(())
                            aria-label="Close"
                        >
                            <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
                            </svg>
                        </button>
                    })}
                </div>

                // Content
                {content}
            </div>
        </div>
    }
}

// ============================================================================
// Specialized Modals
// ============================================================================

/// Confirmation modal for joining a realm.
#[component]
pub fn JoinRealmModal(
    #[prop(into)] open: Signal<bool>,
    realm_name: String,
    realm_slug: String,
    #[prop(into)] pending: Signal<bool>,
    on_confirm: Callback<()>,
    on_cancel: Callback<()>,
) -> impl IntoView {
    let on_cancel_backdrop = on_cancel.clone();
    let on_cancel_close = on_cancel.clone();
    let on_cancel_button = on_cancel.clone();

    let (name_sig, _) = signal(realm_name);
    let (slug_sig, _) = signal(realm_slug);

    view! {
        <Show when=move || open.get()>
            <div
                class="fixed inset-0 z-50 flex items-center justify-center"
                role="dialog"
                aria-modal="true"
                aria-labelledby="join-modal-title"
            >
                <div
                    class="absolute inset-0 bg-black/70 backdrop-blur-sm"
                    on:click=move |_| on_cancel_backdrop.run(())
                    aria-hidden="true"
                />

                <div class="relative bg-gray-800 rounded-lg shadow-2xl max-w-md w-full mx-4 p-6 border border-gray-700">
                    <button
                        type="button"
                        class="absolute top-4 right-4 text-gray-400 hover:text-white transition-colors"
                        on:click=move |_| on_cancel_close.run(())
                        aria-label="Close dialog"
                    >
                        <svg
                            class="w-6 h-6"
                            fill="none"
                            stroke="currentColor"
                            viewBox="0 0 24 24"
                            aria-hidden="true"
                        >
                            <path
                                stroke-linecap="round"
                                stroke-linejoin="round"
                                stroke-width="2"
                                d="M6 18L18 6M6 6l12 12"
                            />
                        </svg>
                    </button>

                    <div class="text-center">
                        <div class="mx-auto w-16 h-16 rounded-full bg-blue-600/20 flex items-center justify-center mb-4">
                            <img
                                src="/icons/castle.svg"
                                alt=""
                                class="w-8 h-8"
                                aria-hidden="true"
                            />
                        </div>

                        <h3 id="join-modal-title" class="text-xl font-bold text-white mb-2">
                            "Join " {move || name_sig.get()} "?"
                        </h3>

                        <p class="text-gray-400 mb-6">
                            "You're not a member of "
                            <span class="text-blue-400 font-medium">{move || slug_sig.get()}</span>
                            " yet. Would you like to join this realm?"
                        </p>

                        <div class="flex flex-col sm:flex-row gap-3 justify-center">
                            <button
                                type="button"
                                class="btn-secondary px-6 py-2"
                                on:click=move |_| on_cancel_button.run(())
                                disabled=move || pending.get()
                            >
                                "Cancel"
                            </button>
                            <button
                                type="button"
                                class="btn-primary px-6 py-2"
                                on:click=move |_| on_confirm.run(())
                                disabled=move || pending.get()
                            >
                                {move || if pending.get() { "Joining..." } else { "Join Realm" }}
                            </button>
                        </div>

                        <p class="text-sm text-gray-500 mt-4">
                            "You can leave a realm at any time from your profile settings."
                        </p>
                    </div>
                </div>
            </div>
        </Show>
    }
}

/// Confirmation modal for general actions.
#[component]
pub fn ConfirmModal(
    #[prop(into)] open: Signal<bool>,
    title: &'static str,
    message: String,
    #[prop(default = "Confirm")] confirm_text: &'static str,
    #[prop(default = "Cancel")] cancel_text: &'static str,
    #[prop(default = false)] destructive: bool,
    #[prop(into)] pending: Signal<bool>,
    on_confirm: Callback<()>,
    on_cancel: Callback<()>,
) -> impl IntoView {
    let on_cancel_backdrop = on_cancel.clone();
    let on_cancel_close = on_cancel.clone();
    let on_cancel_button = on_cancel.clone();

    let (message_sig, _) = signal(message);

    let confirm_class = if destructive {
        "bg-red-600 hover:bg-red-700 text-white px-6 py-2 rounded-lg font-medium transition-colors disabled:opacity-50"
    } else {
        "btn-primary px-6 py-2"
    };

    view! {
        <Show when=move || open.get()>
            <div
                class="fixed inset-0 z-50 flex items-center justify-center"
                role="dialog"
                aria-modal="true"
                aria-labelledby="confirm-modal-title"
            >
                <div
                    class="absolute inset-0 bg-black/70 backdrop-blur-sm"
                    on:click=move |_| on_cancel_backdrop.run(())
                    aria-hidden="true"
                />

                <div class="relative bg-gray-800 rounded-lg shadow-2xl max-w-md w-full mx-4 p-6 border border-gray-700">
                    <button
                        type="button"
                        class="absolute top-4 right-4 text-gray-400 hover:text-white transition-colors"
                        on:click=move |_| on_cancel_close.run(())
                        aria-label="Close dialog"
                    >
                        <svg
                            class="w-6 h-6"
                            fill="none"
                            stroke="currentColor"
                            viewBox="0 0 24 24"
                            aria-hidden="true"
                        >
                            <path
                                stroke-linecap="round"
                                stroke-linejoin="round"
                                stroke-width="2"
                                d="M6 18L18 6M6 6l12 12"
                            />
                        </svg>
                    </button>

                    <div class="text-center">
                        <h3 id="confirm-modal-title" class="text-xl font-bold text-white mb-4">
                            {title}
                        </h3>

                        <p class="text-gray-400 mb-6">{move || message_sig.get()}</p>

                        <div class="flex flex-col sm:flex-row gap-3 justify-center">
                            <button
                                type="button"
                                class="btn-secondary px-6 py-2"
                                on:click=move |_| on_cancel_button.run(())
                                disabled=move || pending.get()
                            >
                                {cancel_text}
                            </button>
                            <button
                                type="button"
                                class=confirm_class
                                on:click=move |_| on_confirm.run(())
                                disabled=move || pending.get()
                            >
                                {move || if pending.get() { "Please wait..." } else { confirm_text }}
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </Show>
    }
}

// ============================================================================
// Guest Locked Overlay
// ============================================================================

/// Overlay displayed when a feature is restricted to registered users.
///
/// Shows a semi-transparent backdrop with a padlock icon and diagonal
/// "Registered Users" text. Designed to be placed inside a modal container
/// with `position: relative`.
///
/// # Example
///
/// ```ignore
/// <div class="relative">
///     // Modal content here
///     <GuestLockedOverlay />
/// </div>
/// ```
#[component]
pub fn GuestLockedOverlay() -> impl IntoView {
    view! {
        <div
            class="absolute inset-0 z-50 flex items-center justify-center bg-gray-900/80 backdrop-blur-sm rounded-lg"
            role="alert"
            aria-label="This feature is restricted to registered users"
        >
            <div class="flex flex-col items-center gap-4 transform -rotate-12">
                <img
                    src="/icons/padlock.svg"
                    alt=""
                    class="w-16 h-16 text-gray-400"
                    style="filter: invert(60%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(90%) contrast(90%);"
                    aria-hidden="true"
                />
                <span class="text-2xl font-bold text-gray-400 tracking-wider uppercase whitespace-nowrap">
                    "Registered Users"
                </span>
            </div>
        </div>
    }
}
