use std::collections::HashMap;
use std::process::{Child, Command, Stdio};
use std::sync::{Arc, Mutex, OnceLock};
use std::time::{Duration, Instant};

use serde::{Deserialize, Serialize};

use crate::process::configure_no_window;

/// 全局后台任务注册表
static TASK_REGISTRY: OnceLock<Arc<Mutex<TaskRegistry>>> = OnceLock::new();

pub fn task_registry() -> Arc<Mutex<TaskRegistry>> {
    TASK_REGISTRY
        .get_or_init(|| Arc::new(Mutex::new(TaskRegistry::default())))
        .clone()
}

#[derive(Debug, Default)]
pub struct TaskRegistry {
    tasks: HashMap<String, BackgroundTask>,
}

#[derive(Debug)]
struct BackgroundTask {
    id: String,
    name: String,
    command: String,
    started_at: Instant,
    child: Option<Child>,
    status: TaskStatus,
    stdout: String,
    stderr: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaskStatus {
    Running,
    Completed { exit_code: i32 },
    Failed { error: String },
    Cancelled,
}

impl From<&TaskStatus> for crate::task::UnifiedTaskStatus {
    fn from(status: &TaskStatus) -> Self {
        match status {
            TaskStatus::Running => Self::Running,
            TaskStatus::Completed { exit_code } => Self::Completed {
                exit_code: *exit_code,
            },
            TaskStatus::Failed { error } => Self::Failed {
                error: error.clone(),
            },
            TaskStatus::Cancelled => Self::Cancelled,
        }
    }
}

impl From<&crate::task::UnifiedTaskStatus> for TaskStatus {
    fn from(status: &crate::task::UnifiedTaskStatus) -> Self {
        match status {
            crate::task::UnifiedTaskStatus::Running
            | crate::task::UnifiedTaskStatus::Queued
            | crate::task::UnifiedTaskStatus::Backgrounded
            | crate::task::UnifiedTaskStatus::Blocked { .. }
            | crate::task::UnifiedTaskStatus::WaitingApproval { .. } => Self::Running,
            crate::task::UnifiedTaskStatus::Completed { exit_code } => Self::Completed {
                exit_code: *exit_code,
            },
            crate::task::UnifiedTaskStatus::Failed { error } => Self::Failed {
                error: error.clone(),
            },
            crate::task::UnifiedTaskStatus::Cancelled => Self::Cancelled,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskInfo {
    pub id: String,
    pub name: String,
    pub command: String,
    pub status: TaskStatus,
    pub duration_ms: u64,
    pub stdout: String,
    pub stderr: String,
}

impl TaskRegistry {
    /// 启动后台任务
    pub fn spawn(
        &mut self,
        name: String,
        cmd: String,
        args: Vec<String>,
        cwd: Option<String>,
        env: Vec<(String, String)>,
    ) -> Result<String, String> {
        let id = scru128::new().to_string();

        let mut command = Command::new(&cmd);
        configure_no_window(&mut command);
        command
            .args(&args)
            .stdout(Stdio::piped())
            .stderr(Stdio::piped());

        if let Some(dir) = &cwd {
            command.current_dir(dir);
        }
        for (k, v) in &env {
            command.env(k, v);
        }

        let child = command
            .spawn()
            .map_err(|e| format!("启动后台任务失败：{e}"))?;

        let cmd_display = if args.is_empty() {
            cmd.clone()
        } else {
            format!("{} {}", cmd, args.join(" "))
        };

        self.tasks.insert(
            id.clone(),
            BackgroundTask {
                id: id.clone(),
                name,
                command: cmd_display,
                started_at: Instant::now(),
                child: Some(child),
                status: TaskStatus::Running,
                stdout: String::new(),
                stderr: String::new(),
            },
        );

        Ok(id)
    }

    /// 查询任务状态（自动收集已完成任务的输出）
    pub fn query(&mut self, task_id: &str) -> Option<TaskInfo> {
        let task = self.tasks.get_mut(task_id)?;

        // 如果还在运行，检查是否已完成
        if matches!(task.status, TaskStatus::Running)
            && let Some(ref mut child) = task.child
        {
            match child.try_wait() {
                Ok(Some(status)) => {
                    // 收集输出
                    let child = task.child.take().unwrap();
                    if let Ok(output) = child.wait_with_output() {
                        task.stdout = String::from_utf8_lossy(&output.stdout).to_string();
                        task.stderr = String::from_utf8_lossy(&output.stderr).to_string();
                    }
                    task.status = TaskStatus::Completed {
                        exit_code: status.code().unwrap_or(-1),
                    };
                }
                Ok(None) => {} // 还在运行
                Err(e) => {
                    task.status = TaskStatus::Failed {
                        error: e.to_string(),
                    };
                }
            }
        }

        Some(TaskInfo {
            id: task.id.clone(),
            name: task.name.clone(),
            command: task.command.clone(),
            status: task.status.clone(),
            duration_ms: task.started_at.elapsed().as_millis() as u64,
            stdout: task.stdout.clone(),
            stderr: task.stderr.clone(),
        })
    }

    /// 列出所有任务
    pub fn list(&mut self) -> Vec<TaskInfo> {
        let ids: Vec<String> = self.tasks.keys().cloned().collect();
        ids.iter().filter_map(|id| self.query(id)).collect()
    }

    /// 列出运行中的任务
    pub fn list_running(&mut self) -> Vec<TaskInfo> {
        self.list()
            .into_iter()
            .filter(|t| matches!(t.status, TaskStatus::Running))
            .collect()
    }

    /// 取消任务
    pub fn cancel(&mut self, task_id: &str) -> Option<TaskInfo> {
        let task = self.tasks.get_mut(task_id)?;
        if let Some(ref mut child) = task.child {
            let _ = child.kill();
            let child = task.child.take().unwrap();
            if let Ok(output) = child.wait_with_output() {
                task.stdout = String::from_utf8_lossy(&output.stdout).to_string();
                task.stderr = String::from_utf8_lossy(&output.stderr).to_string();
            }
        }
        task.status = TaskStatus::Cancelled;

        Some(TaskInfo {
            id: task.id.clone(),
            name: task.name.clone(),
            command: task.command.clone(),
            status: task.status.clone(),
            duration_ms: task.started_at.elapsed().as_millis() as u64,
            stdout: task.stdout.clone(),
            stderr: task.stderr.clone(),
        })
    }

    /// 清理已完成的任务
    pub fn cleanup_completed(&mut self) {
        self.tasks
            .retain(|_, t| matches!(t.status, TaskStatus::Running));
    }

    /// 收集指定任务的最新状态（内部方法，不返回 TaskInfo）
    fn refresh_task_status(&mut self, task_id: &str) {
        let Some(task) = self.tasks.get_mut(task_id) else {
            return;
        };
        if !matches!(task.status, TaskStatus::Running) {
            return;
        }
        if let Some(ref mut child) = task.child {
            match child.try_wait() {
                Ok(Some(status)) => {
                    let child = task.child.take().unwrap();
                    if let Ok(output) = child.wait_with_output() {
                        task.stdout = String::from_utf8_lossy(&output.stdout).to_string();
                        task.stderr = String::from_utf8_lossy(&output.stderr).to_string();
                    }
                    task.status = TaskStatus::Completed {
                        exit_code: status.code().unwrap_or(-1),
                    };
                }
                Ok(None) => {}
                Err(e) => {
                    task.status = TaskStatus::Failed {
                        error: e.to_string(),
                    };
                }
            }
        }
    }

    /// 检查指定的任务是否全部完成（非 Running）
    fn all_finished(&mut self, task_ids: &[String]) -> bool {
        for id in task_ids {
            self.refresh_task_status(id);
            if let Some(task) = self.tasks.get(id)
                && matches!(task.status, TaskStatus::Running)
            {
                return false;
            }
        }
        true
    }
}

/// 等待多个后台任务完成（spawn+join 模式）
///
/// 在持有锁外轮询，避免长时间阻塞其他操作。
/// `timeout_ms` 为 0 表示无限等待。
pub fn wait_tasks(task_ids: Vec<String>, timeout_ms: u64) -> Vec<TaskInfo> {
    let registry = task_registry();
    let deadline = if timeout_ms > 0 {
        Some(Instant::now() + Duration::from_millis(timeout_ms))
    } else {
        None
    };

    loop {
        // 短暂持锁检查状态
        {
            let mut reg = match registry.lock() {
                Ok(reg) => reg,
                Err(_) => break,
            };
            if reg.all_finished(&task_ids) {
                // 全部完成，收集结果
                return task_ids.iter().filter_map(|id| reg.query(id)).collect();
            }
        }

        // 检查超时
        if let Some(dl) = deadline
            && Instant::now() >= dl
        {
            // 超时，返回当前状态
            let mut reg = match registry.lock() {
                Ok(reg) => reg,
                Err(_) => break,
            };
            return task_ids.iter().filter_map(|id| reg.query(id)).collect();
        }

        // 释放锁后短暂休眠，避免忙等
        std::thread::sleep(Duration::from_millis(200));
    }

    Vec::new()
}
