use gloo_storage::{LocalStorage, Storage};
use leptos::prelude::*;
use leptos::task::spawn_local;

const ONBOARDING_COMPLETE_KEY: &str = "onboarding_complete";
const ONBOARDING_STEP_KEY: &str = "onboarding_current_step";

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum WizardStep {
    Welcome = 0,
    Prerequisites = 1,
    Workspace = 2,
    DeploymentMode = 3,
    FirstDeploy = 4,
    Complete = 5,
}

impl WizardStep {
    fn next(self) -> Option<Self> {
        match self {
            Self::Welcome => Some(Self::Prerequisites),
            Self::Prerequisites => Some(Self::Workspace),
            Self::Workspace => Some(Self::DeploymentMode),
            Self::DeploymentMode => Some(Self::FirstDeploy),
            Self::FirstDeploy => Some(Self::Complete),
            Self::Complete => None,
        }
    }

    fn prev(self) -> Option<Self> {
        match self {
            Self::Welcome => None,
            Self::Prerequisites => Some(Self::Welcome),
            Self::Workspace => Some(Self::Prerequisites),
            Self::DeploymentMode => Some(Self::Workspace),
            Self::FirstDeploy => Some(Self::DeploymentMode),
            Self::Complete => Some(Self::FirstDeploy),
        }
    }

    fn title(&self) -> &'static str {
        match self {
            Self::Welcome => "Welcome to Provisioning Platform",
            Self::Prerequisites => "System Prerequisites",
            Self::Workspace => "Configure Workspace",
            Self::DeploymentMode => "Choose Deployment Mode",
            Self::FirstDeploy => "Deploy Infrastructure",
            Self::Complete => "Setup Complete",
        }
    }

    fn as_number(&self) -> usize {
        *self as usize
    }
}

#[component]
pub fn WelcomeWizard(
    #[prop(into)] on_complete: Callback<()>,
    #[prop(optional)] on_skip: Option<Callback<()>>,
) -> impl IntoView {
    let (current_step, set_current_step) = signal(WizardStep::Welcome);
    let (is_visible, set_is_visible) = signal(true);

    // Load saved step on mount
    Effect::new(move |_| {
        if let Ok(step_num) = LocalStorage::get::<usize>(ONBOARDING_STEP_KEY) {
            let step = match step_num {
                0 => WizardStep::Welcome,
                1 => WizardStep::Prerequisites,
                2 => WizardStep::Workspace,
                3 => WizardStep::DeploymentMode,
                4 => WizardStep::FirstDeploy,
                _ => WizardStep::Complete,
            };
            set_current_step.set(step);
        }
    });

    // Save step on change
    Effect::new(move |_| {
        let step = current_step.get();
        let _ = LocalStorage::set(ONBOARDING_STEP_KEY, step.as_number());
    });

    let next_step = move |_| {
        if let Some(next) = current_step.get().next() {
            set_current_step.set(next);

            if next == WizardStep::Complete {
                let _ = LocalStorage::set(ONBOARDING_COMPLETE_KEY, true);
                on_complete.run(());
            }
        }
    };

    let prev_step = move |_| {
        if let Some(prev) = current_step.get().prev() {
            set_current_step.set(prev);
        }
    };

    let skip_wizard = move |_| {
        let _ = LocalStorage::set(ONBOARDING_COMPLETE_KEY, true);
        set_is_visible.set(false);
        if let Some(skip_cb) = on_skip {
            skip_cb.run(());
        }
    };

    let progress_percent = move || {
        let step = current_step.get().as_number();
        (step as f64 / 5.0 * 100.0) as usize
    };

    view! {
        <Show when=move || is_visible.get()>
            <div class="wizard-overlay" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 9998; display: flex; align-items: center; justify-content: center;">
                <div class="wizard-container" style="background: white; border-radius: 12px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); max-width: 700px; width: 90%; max-height: 90vh; overflow-y: auto; position: relative;">
                    // Close button
                    <button
                        on:click=skip_wizard
                        style="position: absolute; top: 20px; right: 20px; background: transparent; border: none; font-size: 1.5rem; cursor: pointer; color: #666; padding: 5px 10px;"
                        title="Skip wizard"
                    >
                        "×"
                    </button>

                    // Progress bar
                    <div style="padding: 30px 40px 20px 40px;">
                        <div style="background: #e5e7eb; height: 6px; border-radius: 3px; overflow: hidden; margin-bottom: 20px;">
                            <div
                                style=move || format!(
                                    "background: #3b82f6; height: 100%; width: {}%; transition: width 0.3s ease;",
                                    progress_percent()
                                )
                            />
                        </div>

                        <h2 style="margin: 0 0 10px 0; font-size: 1.8rem; color: #1f2937;">
                            {move || current_step.get().title()}
                        </h2>

                        <p style="margin: 0; color: #6b7280; font-size: 0.9rem;">
                            {move || format!("Step {} of 5", current_step.get().as_number() + 1)}
                        </p>
                    </div>

                    // Step content
                    <div style="padding: 20px 40px 30px 40px;">
                        {move || match current_step.get() {
                            WizardStep::Welcome => view! {
                                <WelcomeStep />
                            }.into_any(),
                            WizardStep::Prerequisites => view! {
                                <PrerequisitesStep />
                            }.into_any(),
                            WizardStep::Workspace => view! {
                                <WorkspaceStep />
                            }.into_any(),
                            WizardStep::DeploymentMode => view! {
                                <DeploymentModeStep />
                            }.into_any(),
                            WizardStep::FirstDeploy => view! {
                                <FirstDeployStep />
                            }.into_any(),
                            WizardStep::Complete => view! {
                                <CompleteStep />
                            }.into_any(),
                        }}
                    </div>

                    // Navigation buttons
                    <div style="padding: 20px 40px 30px 40px; border-top: 1px solid #e5e7eb; display: flex; justify-content: space-between; align-items: center;">
                        <Show when=move || current_step.get().prev().is_some()>
                            <button
                                on:click=prev_step
                                style="padding: 10px 24px; background: #f3f4f6; color: #374151; border: none; border-radius: 6px; font-weight: 500; cursor: pointer; font-size: 1rem;"
                            >
                                "← Previous"
                            </button>
                        </Show>

                        <div style="flex: 1;" />

                        <Show when=move || current_step.get() != WizardStep::Complete>
                            <button
                                on:click=next_step
                                style="padding: 10px 24px; background: #3b82f6; color: white; border: none; border-radius: 6px; font-weight: 500; cursor: pointer; font-size: 1rem;"
                            >
                                {move || if current_step.get().next() == Some(WizardStep::Complete) {
                                    "Finish"
                                } else {
                                    "Next →"
                                }}
                            </button>
                        </Show>
                    </div>
                </div>
            </div>
        </Show>
    }
}

#[component]
fn WelcomeStep() -> impl IntoView {
    view! {
        <div style="padding: 20px 0;">
            <div style="text-align: center; margin-bottom: 30px;">
                <div style="font-size: 4rem; margin-bottom: 20px;">
                    "🚀"
                </div>
                <h3 style="font-size: 1.3rem; color: #1f2937; margin-bottom: 15px;">
                    "Welcome to the Provisioning Platform"
                </h3>
                <p style="color: #6b7280; line-height: 1.6; max-width: 500px; margin: 0 auto;">
                    "This wizard will guide you through setting up your infrastructure automation environment. "
                    "You'll configure your workspace, choose a deployment mode, and deploy your first infrastructure."
                </p>
            </div>

            <div style="background: #f9fafb; padding: 20px; border-radius: 8px; border-left: 4px solid #3b82f6;">
                <h4 style="margin: 0 0 10px 0; color: #1f2937; font-size: 1rem;">
                    "What you'll accomplish:"
                </h4>
                <ul style="margin: 0; padding-left: 20px; color: #6b7280; line-height: 1.8;">
                    <li>"Check system prerequisites (Nushell, Docker, etc.)"</li>
                    <li>"Configure your workspace"</li>
                    <li>"Choose deployment mode (Solo, Multi-User, CI/CD, Enterprise)"</li>
                    <li>"Deploy your first infrastructure"</li>
                </ul>
            </div>

            <div style="margin-top: 20px; padding: 15px; background: #fef3c7; border-radius: 8px; border-left: 4px solid #f59e0b;">
                <p style="margin: 0; color: #92400e; font-size: 0.9rem;">
                    <strong>"💡 Tip:"</strong>" You can skip this wizard and configure everything manually later from the Settings page."
                </p>
            </div>
        </div>
    }
}

#[component]
fn PrerequisitesStep() -> impl IntoView {
    let (nushell_ok, set_nushell_ok) = signal(false);
    let (docker_ok, set_docker_ok) = signal(false);
    let (kcl_ok, set_kcl_ok) = signal(false);

    // TODO: Actually check these via API
    Effect::new(move |_| {
        spawn_local(async move {
            // Simulate checking prerequisites
            use wasm_bindgen_futures::JsFuture;
            use web_sys::window;

            if let Some(window) = window() {
                let promise = js_sys::Promise::new(&mut |resolve, _reject| {
                    window
                        .set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, 1000)
                        .ok();
                });
                let _ = JsFuture::from(promise).await;
            }

            set_nushell_ok.set(true);
            set_docker_ok.set(true);
            set_kcl_ok.set(true);
        });
    });

    view! {
        <div style="padding: 20px 0;">
            <p style="color: #6b7280; margin-bottom: 25px; line-height: 1.6;">
                "Let's verify that your system has the required tools installed. "
                "These are necessary for the provisioning platform to function correctly."
            </p>

            <div style="display: flex; flex-direction: column; gap: 15px;">
                <PrerequisiteItem
                    name="Nushell 0.107.1+"
                    description="Primary shell and scripting language"
                    status=nushell_ok
                    install_cmd="brew install nushell"
                />
                <PrerequisiteItem
                    name="Docker"
                    description="Container runtime for test environments"
                    status=docker_ok
                    install_cmd="brew install docker"
                />
                <PrerequisiteItem
                    name="KCL 0.11.2+"
                    description="Configuration language for infrastructure"
                    status=kcl_ok
                    install_cmd="brew install kcl"
                />
            </div>

            <div style="margin-top: 25px; padding: 15px; background: #f0f9ff; border-radius: 8px; border-left: 4px solid #3b82f6;">
                <p style="margin: 0; color: #1e40af; font-size: 0.9rem;">
                    <strong>"ℹ️ Note:"</strong>" Some features may work without all prerequisites, but full functionality requires all tools to be installed."
                </p>
            </div>
        </div>
    }
}

#[component]
fn PrerequisiteItem(
    name: &'static str,
    description: &'static str,
    #[prop(into)] status: Signal<bool>,
    install_cmd: &'static str,
) -> impl IntoView {
    view! {
        <div style="padding: 15px; background: #f9fafb; border-radius: 8px; border: 1px solid #e5e7eb;">
            <div style="display: flex; align-items: start; gap: 12px;">
                <div style="font-size: 1.5rem; margin-top: 2px;">
                    {move || if status.get() { "✅" } else { "⏳" }}
                </div>
                <div style="flex: 1;">
                    <h4 style="margin: 0 0 5px 0; color: #1f2937; font-size: 1rem;">
                        {name}
                    </h4>
                    <p style="margin: 0 0 10px 0; color: #6b7280; font-size: 0.85rem;">
                        {description}
                    </p>
                    <Show when=move || !status.get()>
                        <code style="background: #1f2937; color: #10b981; padding: 6px 10px; border-radius: 4px; font-size: 0.8rem; display: inline-block;">
                            {install_cmd}
                        </code>
                    </Show>
                </div>
            </div>
        </div>
    }
}

#[component]
fn WorkspaceStep() -> impl IntoView {
    let (workspace_name, set_workspace_name) = signal(String::from("my-workspace"));

    view! {
        <div style="padding: 20px 0;">
            <p style="color: #6b7280; margin-bottom: 25px; line-height: 1.6;">
                "A workspace is where your infrastructure configurations, state, and data are stored. "
                "You can create multiple workspaces for different environments."
            </p>

            <div style="margin-bottom: 20px;">
                <label style="display: block; margin-bottom: 8px; color: #374151; font-weight: 500;">
                    "Workspace Name"
                </label>
                <input
                    type="text"
                    placeholder="my-workspace"
                    prop:value=move || workspace_name.get()
                    on:input=move |ev| set_workspace_name.set(event_target_value(&ev))
                    style="width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 1rem;"
                />
                <p style="margin: 8px 0 0 0; color: #6b7280; font-size: 0.85rem;">
                    "Choose a descriptive name (e.g., 'production', 'staging', 'dev')"
                </p>
            </div>

            <div style="background: #f9fafb; padding: 20px; border-radius: 8px; border: 1px solid #e5e7eb;">
                <h4 style="margin: 0 0 15px 0; color: #1f2937; font-size: 1rem;">
                    "Workspace Structure"
                </h4>
                <div style="font-family: monospace; font-size: 0.85rem; color: #374151; line-height: 1.8;">
                    <div>"workspace/"</div>
                    <div style="padding-left: 20px;">"├── config/ " <span style="color: #6b7280;">"# Configuration files"</span></div>
                    <div style="padding-left: 20px;">"├── infra/ " <span style="color: #6b7280;">"# Infrastructure definitions"</span></div>
                    <div style="padding-left: 20px;">"├── runtime/ " <span style="color: #6b7280;">"# Runtime data and state"</span></div>
                    <div style="padding-left: 20px;">"└── extensions/ " <span style="color: #6b7280;">"# Custom extensions"</span></div>
                </div>
            </div>
        </div>
    }
}

#[component]
fn DeploymentModeStep() -> impl IntoView {
    let (selected_mode, set_selected_mode) = signal(String::from("solo"));

    let modes = vec![
        (
            "solo",
            "Solo",
            "2 CPU / 4GB RAM",
            "Perfect for development and testing",
        ),
        (
            "multiuser",
            "Multi-User",
            "4 CPU / 8GB RAM",
            "Team collaboration with shared resources",
        ),
        (
            "cicd",
            "CI/CD",
            "8 CPU / 16GB RAM",
            "Continuous integration and deployment",
        ),
        (
            "enterprise",
            "Enterprise",
            "16 CPU / 32GB RAM",
            "Large-scale production deployments",
        ),
    ];

    view! {
        <div style="padding: 20px 0;">
            <p style="color: #6b7280; margin-bottom: 25px; line-height: 1.6;">
                "Choose a deployment mode that matches your use case. "
                "This determines resource allocation and available features."
            </p>

            <div style="display: grid; gap: 15px;">
                {modes.into_iter().map(|(id, name, resources, desc)| {
                    let mode_id = id.to_string();
                    let mode_id_click = mode_id.clone();
                    let mode_id_style = mode_id.clone();
                    let mode_id_icon = mode_id.clone();
                    view! {
                        <div
                            on:click=move |_| set_selected_mode.set(mode_id_click.clone())
                            style=move || format!(
                                "padding: 20px; border-radius: 8px; cursor: pointer; border: 2px solid {}; background: {}; transition: all 0.2s;",
                                if selected_mode.get() == mode_id_style { "#3b82f6" } else { "#e5e7eb" },
                                if selected_mode.get() == mode_id_style { "#eff6ff" } else { "white" }
                            )
                        >
                            <div style="display: flex; align-items: start; gap: 15px;">
                                <div style="font-size: 1.2rem; margin-top: 2px;">
                                    {move || if selected_mode.get() == mode_id_icon { "🔵" } else { "⚪" }}
                                </div>
                                <div style="flex: 1;">
                                    <h4 style="margin: 0 0 5px 0; color: #1f2937; font-size: 1.1rem;">
                                        {name}
                                    </h4>
                                    <p style="margin: 0 0 8px 0; color: #3b82f6; font-size: 0.85rem; font-weight: 500;">
                                        {resources}
                                    </p>
                                    <p style="margin: 0; color: #6b7280; font-size: 0.9rem;">
                                        {desc}
                                    </p>
                                </div>
                            </div>
                        </div>
                    }
                }).collect_view()}
            </div>
        </div>
    }
}

#[component]
fn FirstDeployStep() -> impl IntoView {
    let (deploying, set_deploying) = signal(false);
    let (deploy_status, set_deploy_status) = signal(String::from(""));

    let start_deploy = move |_| {
        set_deploying.set(true);
        spawn_local(async move {
            use wasm_bindgen_futures::JsFuture;
            use web_sys::window;

            let sleep = |ms: i32| async move {
                if let Some(window) = window() {
                    let promise = js_sys::Promise::new(&mut |resolve, _reject| {
                        window
                            .set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, ms)
                            .ok();
                    });
                    let _ = JsFuture::from(promise).await;
                }
            };

            set_deploy_status.set("Initializing workspace...".to_string());
            sleep(1000).await;

            set_deploy_status.set("Creating infrastructure configuration...".to_string());
            sleep(1000).await;

            set_deploy_status.set("Deploying orchestrator...".to_string());
            sleep(1500).await;

            set_deploy_status.set("Deployment complete! ✅".to_string());
            set_deploying.set(false);
        });
    };

    view! {
        <div style="padding: 20px 0;">
            <p style="color: #6b7280; margin-bottom: 25px; line-height: 1.6;">
                "Ready to deploy your first infrastructure! "
                "This will set up the orchestrator and create a basic configuration."
            </p>

            <Show when=move || !deploying.get() && deploy_status.get().is_empty()>
                <button
                    on:click=start_deploy
                    style="width: 100%; padding: 15px; background: #10b981; color: white; border: none; border-radius: 8px; font-size: 1.1rem; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 10px;"
                >
                    <span>"🚀"</span>
                    <span>"Start Deployment"</span>
                </button>
            </Show>

            <Show when=move || deploying.get() || !deploy_status.get().is_empty()>
                <div style="padding: 20px; background: #f9fafb; border-radius: 8px; border: 1px solid #e5e7eb;">
                    <div style="display: flex; align-items: center; gap: 15px; margin-bottom: 15px;">
                        <Show when=move || deploying.get()>
                            <div style="width: 20px; height: 20px; border: 3px solid #3b82f6; border-top-color: transparent; border-radius: 50%; animation: spin 1s linear infinite;" />
                        </Show>
                        <p style="margin: 0; color: #1f2937; font-weight: 500;">
                            {move || deploy_status.get()}
                        </p>
                    </div>
                </div>
            </Show>

            <div style="margin-top: 25px; background: #fef3c7; padding: 15px; border-radius: 8px; border-left: 4px solid #f59e0b;">
                <p style="margin: 0; color: #92400e; font-size: 0.9rem;">
                    <strong>"💡 Tip:"</strong>" You can monitor deployment progress in the Workflows page after completing the wizard."
                </p>
            </div>

            <style>
                "@keyframes spin {
                    to { transform: rotate(360deg); }
                }"
            </style>
        </div>
    }
}

#[component]
fn CompleteStep() -> impl IntoView {
    view! {
        <div style="padding: 20px 0; text-align: center;">
            <div style="font-size: 5rem; margin-bottom: 20px;">
                "🎉"
            </div>
            <h3 style="font-size: 1.5rem; color: #1f2937; margin-bottom: 15px;">
                "Setup Complete!"
            </h3>
            <p style="color: #6b7280; line-height: 1.6; margin-bottom: 30px;">
                "Your provisioning platform is ready to use. "
                "You can now start managing your infrastructure."
            </p>

            <div style="background: #f0fdf4; padding: 25px; border-radius: 8px; border: 1px solid #86efac; margin-bottom: 25px;">
                <h4 style="margin: 0 0 15px 0; color: #166534; font-size: 1.1rem;">
                    "Next Steps:"
                </h4>
                <ul style="margin: 0; padding-left: 20px; color: #15803d; line-height: 2; text-align: left;">
                    <li>"Create servers in the Servers page"</li>
                    <li>"Install task services (Kubernetes, etc.)"</li>
                    <li>"Deploy complete clusters"</li>
                    <li>"Monitor workflows and tasks"</li>
                    <li>"Explore the documentation"</li>
                </ul>
            </div>

            <div style="display: flex; gap: 15px; justify-content: center;">
                <a
                    href="/dashboard"
                    style="padding: 12px 24px; background: #3b82f6; color: white; text-decoration: none; border-radius: 6px; font-weight: 500;"
                >
                    "Go to Dashboard"
                </a>
                <a
                    href="/servers"
                    style="padding: 12px 24px; background: #10b981; color: white; text-decoration: none; border-radius: 6px; font-weight: 500;"
                >
                    "Create Server"
                </a>
            </div>
        </div>
    }
}
