use std::collections::HashMap;

use leptos::prelude::*;
use leptos::task::spawn_local;
use serde::{Deserialize, Serialize};

use crate::api::iac::{
    fetch_deployment_status as api_fetch_deployment_status,
    fetch_deployments as api_fetch_deployments, submit_deployment as api_submit_deployment,
    DeploymentTask as ApiDeploymentTask,
};
use crate::components::LoadingSpinner;
use crate::config::endpoints;
use crate::services::websocket::{ConnectionState, SubscriptionRequest, WebSocketService};

/// Deployment task
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct DeploymentTask {
    pub id: String,
    pub task_type: String,
    pub name: String,
    pub description: String,
    pub depends_on: Vec<String>,
    pub parameters: serde_json::Value,
    pub status: TaskStatus,
    pub estimated_duration_seconds: Option<u32>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum TaskStatus {
    Pending,
    Running,
    Completed,
    Failed,
}

/// Complete deployment plan
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentPlan {
    pub id: String,
    pub name: String,
    pub description: String,
    pub organization: String,
    pub tasks: Vec<DeploymentTask>,
    pub created_at: String,
    pub scheduled_at: Option<String>,
}

/// Deployment Plan Preview Page
#[component]
pub fn DeploymentPreviewPage() -> impl IntoView {
    let (plans, set_plans) = signal::<Vec<DeploymentPlan>>(vec![]);
    let (loading, set_loading) = signal(true);
    let (error, set_error) = signal::<Option<String>>(None);
    let (selected_plan, set_selected_plan) = signal::<Option<String>>(None);

    Effect::new(move |_| {
        spawn_local(async move {
            set_loading.set(true);
            set_error.set(None);
            match fetch_deployment_plans().await {
                Ok(results) => {
                    set_plans.set(results);
                }
                Err(e) => {
                    set_error.set(Some(format!("Failed to load deployment plans: {}", e)));
                }
            }
            set_loading.set(false);
        });
    });

    view! {
        <div class="min-h-screen bg-base-200 p-6">
            <div class="container mx-auto">
                // Header
                <div class="mb-8">
                    <h1 class="text-4xl font-bold text-base-content mb-2">
                        "Deployment Plan Preview"
                    </h1>
                    <p class="text-base-content/70">
                        "View infrastructure deployment plans with timeline and resource requirements"
                    </p>
                </div>

                <div class="space-y-6">
                    // Error display
                    <Show when=move || error.get().is_some()>
                        <div class="alert alert-error shadow-lg">
                            <div>
                                <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l-2-2m0 0l-2-2m2 2l2-2m-2 2l-2 2m8-8l-2 2m0 0l-2-2m2 2l2-2m-2 2l-2 2" />
                                </svg>
                                <span>{error.get().unwrap_or_default()}</span>
                            </div>
                        </div>
                    </Show>

                    // Loading state
                    <Show when=move || loading.get()>
                        <div class="flex justify-center items-center py-12">
                            <LoadingSpinner size="loading-lg" />
                        </div>
                    </Show>

                    // Deployment plans list
                    <Show when=move || !plans.get().is_empty()>
                        <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
                            {plans.get().into_iter().map(|plan| {
                                view! {
                                    <DeploymentPlanCard
                                        plan=plan.clone()
                                        on_select=Callback::new(move |_| {
                                            set_selected_plan.set(Some(plan.id.clone()));
                                        })
                                    />
                                }
                            }).collect_view()}
                        </div>
                    </Show>

                    <Show when=move || plans.get().is_empty() && !loading.get()>
                        <div class="alert">
                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current flex-shrink-0 w-6 h-6">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
                            </svg>
                            <span>"No deployment plans found. Generate a plan from detected infrastructure."</span>
                        </div>
                    </Show>

                    // Detail view for selected plan
                    <Show when=move || selected_plan.get().is_some()>
                        {selected_plan.get().and_then(|id| {
                            plans.get().into_iter().find(|p| p.id == id).map(|plan| {
                                view! {
                                    <DeploymentPlanDetail
                                        plan=plan
                                        on_close=Callback::new(move |_| {
                                            set_selected_plan.set(None);
                                        })
                                    />
                                }
                            })
                        })}
                    </Show>
                </div>
            </div>
        </div>
    }
}

/// Deployment plan card
#[component]
pub fn DeploymentPlanCard(plan: DeploymentPlan, on_select: Callback<()>) -> impl IntoView {
    let total_duration = plan
        .tasks
        .iter()
        .filter_map(|t| t.estimated_duration_seconds)
        .sum::<u32>();

    let completed_tasks = plan
        .tasks
        .iter()
        .filter(|t| t.status == TaskStatus::Completed)
        .count();

    view! {
        <div class="card bg-base-100 shadow-md hover:shadow-lg transition-shadow">
            <div class="card-body">
                <div class="flex justify-between items-start mb-4">
                    <div>
                        <h2 class="card-title text-2xl">{plan.name.clone()}</h2>
                        <p class="text-sm text-base-content/60">{plan.organization.clone()}</p>
                    </div>
                    <div class="text-right badge badge-lg badge-primary">
                        {plan.tasks.len()} " tasks"
                    </div>
                </div>

                <p class="text-base-content/80 mb-4">{plan.description.clone()}</p>

                // Progress bar
                <div class="mb-4">
                    <div class="flex justify-between items-center mb-2">
                        <p class="text-sm font-semibold">"Progress"</p>
                        <span class="text-sm">
                            {completed_tasks} "/" {plan.tasks.len()} " completed"
                        </span>
                    </div>
                    <progress
                        class="progress progress-success w-full"
                        value=if plan.tasks.is_empty() { 0 } else { (completed_tasks as f32 / plan.tasks.len() as f32 * 100.0) as i32 }
                        max="100"
                    ></progress>
                </div>

                // Duration and task types
                <div class="space-y-3 mb-4">
                    <div class="flex items-center gap-2 text-sm text-base-content/70">
                        <svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
                            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z" />
                        </svg>
                        <span>"Estimated: " {format_duration(total_duration)}</span>
                    </div>

                    <div>
                        <p class="text-sm font-semibold mb-2">"Task Types"</p>
                        <div class="flex flex-wrap gap-2">
                            {get_unique_task_types(&plan.tasks).into_iter().map(|task_type| {
                                let count = plan.tasks.iter()
                                    .filter(|t| t.task_type == task_type)
                                    .count();
                                view! {
                                    <span class="badge badge-secondary">
                                        {task_type} ": " {count}
                                    </span>
                                }
                            }).collect_view()}
                        </div>
                    </div>
                </div>

                <div class="card-actions justify-end">
                    <button
                        on:click=move |_| on_select.run(())
                        class="btn btn-primary btn-sm"
                    >
                        "View Timeline"
                    </button>
                </div>
            </div>
        </div>
    }
}

/// Detailed view of deployment plan with timeline
#[component]
pub fn DeploymentPlanDetail(plan: DeploymentPlan, on_close: Callback<()>) -> impl IntoView {
    // Track reactive task updates
    let (tasks, set_tasks) = signal(plan.tasks.clone());
    let (overall_status, set_overall_status) = signal("Pending".to_string());
    let (ws_connected, set_ws_connected) = signal(false);

    let plan_id = plan.id.clone();
    let config = crate::config::use_config();

    // Set up WebSocket connection and subscription
    Effect::new(move |_| {
        let plan_id = plan_id.clone();
        let ws_url = "ws://localhost:3001/ws".to_string();

        spawn_local(async move {
            // Create WebSocket service
            let ws_service = WebSocketService::new();
            let mut connection = ws_service.connect(&ws_url);

            // Subscribe to deployment status updates
            let mut filters = HashMap::new();
            filters.insert(
                "deployment_id".to_string(),
                serde_json::json!(plan_id.clone()),
            );

            if let Err(e) = connection.subscribe_to_topic("deployment_status", Some(filters)) {
                tracing::warn!("Failed to subscribe to deployment status: {}", e);
            }

            set_ws_connected.set(connection.is_connected());

            // Listen for incoming deployment status messages
            Effect::new(move |_| {
                if let Some(message) = connection.message_stream.get() {
                    if message.message_type == "deployment_status" {
                        // Parse the status update
                        if let Ok(status_update) =
                            serde_json::from_value::<DeploymentStatusUpdate>(message.data)
                        {
                            // Update task status
                            if status_update.deployment_id == plan_id {
                                set_tasks.update(|tasks| {
                                    if let Some(task) =
                                        tasks.iter_mut().find(|t| t.id == status_update.task_id)
                                    {
                                        task.status = status_update.status.clone();
                                    }
                                });

                                // Update overall status
                                set_overall_status.set(
                                    status_update.overall_status.unwrap_or_else(|| {
                                        let completed = tasks
                                            .get()
                                            .iter()
                                            .filter(|t| t.status == TaskStatus::Completed)
                                            .count();
                                        if completed == tasks.get().len() {
                                            "Completed".to_string()
                                        } else if tasks
                                            .get()
                                            .iter()
                                            .any(|t| t.status == TaskStatus::Failed)
                                        {
                                            "Failed".to_string()
                                        } else if tasks
                                            .get()
                                            .iter()
                                            .any(|t| t.status == TaskStatus::Running)
                                        {
                                            "Running".to_string()
                                        } else {
                                            "Pending".to_string()
                                        }
                                    }),
                                );
                            }
                        }
                    }
                }
            });
        });
    });

    view! {
        <div class="card bg-base-100 shadow-lg">
            <div class="card-body">
                <div class="flex justify-between items-center mb-6">
                    <h2 class="card-title text-3xl">{plan.name.clone()} " - Timeline"</h2>
                    <button
                        on:click=move |_| on_close.run(())
                        class="btn btn-ghost btn-circle btn-sm"
                    >
                        <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                        </svg>
                    </button>
                </div>

                // Plan metadata
                <div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
                    <div class="stat bg-base-200 rounded">
                        <div class="stat-title">"Organization"</div>
                        <div class="stat-value text-lg">{plan.organization.clone()}</div>
                    </div>
                    <div class="stat bg-base-200 rounded">
                        <div class="stat-title">"Total Tasks"</div>
                        <div class="stat-value text-lg text-primary">{plan.tasks.len()}</div>
                    </div>
                    <div class="stat bg-base-200 rounded">
                        <div class="stat-title">"Created"</div>
                        <div class="stat-value text-lg">{shorten_date(&plan.created_at)}</div>
                    </div>
                    <div class="stat bg-base-200 rounded">
                        <div class="stat-title">"Status"</div>
                        <div class="stat-value text-lg text-warning">{overall_status}</div>
                    </div>
                </div>

                // WebSocket connection indicator
                <Show when=move || ws_connected.get()>
                    <div class="alert alert-success mb-4">
                        <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
                        </svg>
                        <span>"Real-time updates enabled"</span>
                    </div>
                </Show>

                // Timeline
                <div>
                    <h3 class="text-xl font-bold mb-6">"Deployment Timeline"</h3>
                    <div class="space-y-4">
                        {move || {
                            tasks.get().into_iter().enumerate().map(|(idx, task)| {
                                view! {
                                    <DeploymentTaskTimeline
                                        task=task
                                        is_last=idx == tasks.get().len() - 1
                                    />
                                }
                            }).collect_view()
                        }}
                    </div>
                </div>
            </div>
        </div>
    }
}

/// Deployment status update from WebSocket
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentStatusUpdate {
    pub deployment_id: String,
    pub task_id: String,
    pub status: TaskStatus,
    pub overall_status: Option<String>,
    pub timestamp: Option<String>,
}

/// Single task in timeline
#[component]
pub fn DeploymentTaskTimeline(task: DeploymentTask, is_last: bool) -> impl IntoView {
    let (status_badge, status_color) = match task.status {
        TaskStatus::Completed => ("badge-success", "✓"),
        TaskStatus::Running => ("badge-info", "↻"),
        TaskStatus::Failed => ("badge-error", "✕"),
        TaskStatus::Pending => ("badge-ghost", "◯"),
    };

    view! {
        <div class="relative pb-4">
            <div class="flex gap-4">
                // Status indicator
                <div class=format!("badge badge-lg {} flex-shrink-0 w-12 h-12 flex items-center justify-center font-bold", status_badge)>
                    {status_color}
                </div>

                // Content
                <div class="flex-1 pt-1">
                    <div class="flex justify-between items-start mb-2">
                        <div>
                            <h5 class="font-semibold text-base-content">{task.name.clone()}</h5>
                            <p class="text-sm text-base-content/60">{task.task_type.clone()}</p>
                        </div>
                        {task.estimated_duration_seconds.map(|duration| {
                            view! {
                                <span class="text-sm text-base-content/60">
                                    {format_duration(duration)}
                                </span>
                            }
                        })}
                    </div>

                    <p class="text-sm text-base-content/80 mb-3">{task.description.clone()}</p>

                    // Dependencies
                    {if !task.depends_on.is_empty() {
                        view! {
                            <div class="mb-3">
                                <p class="text-xs font-semibold text-base-content/70 mb-2">"Depends on:"</p>
                                <div class="flex flex-wrap gap-2">
                                    {task.depends_on.iter().map(|dep| {
                                        let dep = dep.clone();
                                        view! {
                                            <span class="badge badge-sm">{dep}</span>
                                        }
                                    }).collect_view()}
                                </div>
                            </div>
                        }.into_any()
                    } else {
                        view! { <div></div> }.into_any()
                    }}

                    <span class=format!("badge {}", status_badge)>
                        {format!("{:?}", task.status)}
                    </span>
                </div>
            </div>

            <Show when=move || !is_last>
                <div class="absolute left-6 top-12 w-1 h-4 bg-base-300"></div>
            </Show>
        </div>
    }
}

// Helper functions
fn format_duration(seconds: u32) -> String {
    if seconds < 60 {
        format!("{}s", seconds)
    } else if seconds < 3600 {
        format!("{}m", seconds / 60)
    } else {
        format!("{}h", seconds / 3600)
    }
}

fn get_unique_task_types(tasks: &[DeploymentTask]) -> Vec<String> {
    let mut types: Vec<_> = tasks.iter().map(|t| t.task_type.clone()).collect();
    types.sort();
    types.dedup();
    types
}

fn shorten_date(date_str: &str) -> String {
    date_str.split('T').next().unwrap_or(date_str).to_string()
}

/// Placeholder API call
async fn fetch_deployment_plans() -> Result<Vec<DeploymentPlan>, String> {
    match api_fetch_deployments(Some(1), Some(100)).await {
        Ok(response) => {
            // Transform API response to page types
            let items = response
                .items
                .into_iter()
                .map(|plan| {
                    // Transform ApiDeploymentTask to DeploymentTask
                    let tasks = plan
                        .tasks
                        .into_iter()
                        .map(|task| DeploymentTask {
                            id: task.id,
                            task_type: task.task_type,
                            name: task.name,
                            description: task.description,
                            depends_on: task.depends_on,
                            parameters: task.parameters,
                            status: TaskStatus::Pending,
                            estimated_duration_seconds: None,
                        })
                        .collect();

                    DeploymentPlan {
                        id: plan.id,
                        name: plan.name,
                        description: plan.description,
                        organization: plan.organization,
                        tasks,
                        created_at: plan.created_at,
                        scheduled_at: plan.scheduled_at,
                    }
                })
                .collect();

            Ok(items)
        }
        Err(e) => Err(e),
    }
}
