//! User detail page component.

use leptos::prelude::*;
#[cfg(feature = "hydrate")]
use leptos::task::spawn_local;
use leptos_router::hooks::use_params_map;

use crate::components::{
    Card, DetailGrid, DetailItem, MessageAlert, PageHeader, StatusBadge, TempPasswordDisplay,
};
use crate::hooks::use_fetch_if;
use crate::models::UserDetail;
#[cfg(feature = "hydrate")]
use crate::utils::reload_page;

/// User detail page component.
#[component]
pub fn UserDetailPage() -> impl IntoView {
    let params = use_params_map();
    let user_id = move || params.get().get("user_id").unwrap_or_default();
    let initial_user_id = params.get_untracked().get("user_id").unwrap_or_default();

    let (message, set_message) = signal(Option::<(String, bool)>::None);

    let user = use_fetch_if::<UserDetail>(
        move || !user_id().is_empty(),
        move || format!("/api/admin/users/{}", user_id()),
    );

    view! {
        <PageHeader title="User Details" subtitle=initial_user_id>
            <a href="/admin/users" class="btn btn-secondary">"Back to Users"</a>
        </PageHeader>

        <Suspense fallback=|| view! { <p>"Loading user..."</p> }>
            {move || {
                user.get().map(|maybe_user| {
                    match maybe_user {
                        Some(u) => view! {
                            <UserDetailView user=u message=message set_message=set_message />
                        }.into_any(),
                        None => view! {
                            <Card>
                                <p class="text-error">"User not found or you don't have permission to view."</p>
                            </Card>
                        }.into_any()
                    }
                })
            }}
        </Suspense>
    }
}

#[component]
fn UserDetailView(
    user: UserDetail,
    message: ReadSignal<Option<(String, bool)>>,
    set_message: WriteSignal<Option<(String, bool)>>,
) -> impl IntoView {
    #[cfg(feature = "hydrate")]
    let user_id = user.id.clone();
    #[cfg(feature = "hydrate")]
    let user_id_for_status = user_id.clone();
    #[cfg(feature = "hydrate")]
    let user_id_for_reset = user_id.clone();
    let user_status = user.status.clone();
    let user_status_for_badge = user_status.clone();

    let (pending_status, set_pending_status) = signal(false);
    let (pending_reset, set_pending_reset) = signal(false);
    let (new_password, set_new_password) = signal(Option::<String>::None);

    let update_status = {
        #[allow(unused_variables)]
        move |new_status: &'static str| {
            set_pending_status.set(true);
            set_message.set(None);

            #[cfg(feature = "hydrate")]
            {
                use gloo_net::http::Request;

                let user_id = user_id_for_status.clone();
                let status = new_status.to_string();
                spawn_local(async move {
                    let response = Request::put(&format!("/api/admin/users/{}/status", user_id))
                        .json(&serde_json::json!({ "status": status }))
                        .unwrap()
                        .send()
                        .await;

                    set_pending_status.set(false);

                    match response {
                        Ok(resp) if resp.ok() => {
                            set_message.set(Some(("Status updated!".to_string(), true)));
                            reload_page();
                        }
                        _ => {
                            set_message.set(Some(("Failed to update status".to_string(), false)));
                        }
                    }
                });
            }
        }
    };

    let reset_password = move |_| {
        set_pending_reset.set(true);
        set_message.set(None);
        set_new_password.set(None);

        #[cfg(feature = "hydrate")]
        {
            use gloo_net::http::Request;

            let user_id = user_id_for_reset.clone();
            spawn_local(async move {
                let response =
                    Request::post(&format!("/api/admin/users/{}/reset-password", user_id))
                        .send()
                        .await;

                set_pending_reset.set(false);

                match response {
                    Ok(resp) if resp.ok() => {
                        #[derive(serde::Deserialize)]
                        struct ResetResponse {
                            temporary_password: String,
                        }
                        if let Ok(result) = resp.json::<ResetResponse>().await {
                            set_new_password.set(Some(result.temporary_password));
                            set_message
                                .set(Some(("Password reset successfully!".to_string(), true)));
                        }
                    }
                    _ => {
                        set_message.set(Some(("Failed to reset password".to_string(), false)));
                    }
                }
            });
        }
    };

    view! {
        <Card>
            <div class="user-header">
                <div class="user-info">
                    <h2>{user.display_name.clone()}</h2>
                    <p class="text-muted">"@" {user.username.clone()}</p>
                </div>
                <StatusBadge status=user_status_for_badge />
            </div>

            <DetailGrid>
                <DetailItem label="User ID">
                    <code>{user.id.clone()}</code>
                </DetailItem>
                <DetailItem label="Email">
                    {user.email.clone().unwrap_or_else(|| "Not set".to_string())}
                </DetailItem>
                <DetailItem label="Server Role">
                    {user.server_role.clone().unwrap_or_else(|| "None".to_string())}
                </DetailItem>
                <DetailItem label="Created">
                    {user.created_at.clone()}
                </DetailItem>
                <DetailItem label="Updated">
                    {user.updated_at.clone()}
                </DetailItem>
            </DetailGrid>
        </Card>

        <Card title="Account Actions">
            <MessageAlert message=message />
            <TempPasswordDisplay password=new_password label="New Temporary Password:" />

            <div class="action-buttons">
                <button
                    type="button"
                    class="btn btn-secondary"
                    disabled=move || pending_reset.get()
                    on:click=reset_password
                >
                    {move || if pending_reset.get() { "Resetting..." } else { "Reset Password" }}
                </button>

                {if user_status != "suspended" {
                    let update_status = update_status.clone();
                    view! {
                        <button
                            type="button"
                            class="btn btn-warning"
                            disabled=move || pending_status.get()
                            on:click=move |_| update_status("suspended")
                        >
                            "Suspend User"
                        </button>
                    }.into_any()
                } else {
                    let update_status = update_status.clone();
                    view! {
                        <button
                            type="button"
                            class="btn btn-primary"
                            disabled=move || pending_status.get()
                            on:click=move |_| update_status("active")
                        >
                            "Activate User"
                        </button>
                    }.into_any()
                }}

                {if user_status != "banned" {
                    view! {
                        <button
                            type="button"
                            class="btn btn-danger"
                            disabled=move || pending_status.get()
                            on:click=move |_| update_status("banned")
                        >
                            "Ban User"
                        </button>
                    }.into_any()
                } else {
                    view! {}.into_any()
                }}
            </div>
        </Card>
    }
}
