//! 核心类型定义：ID 别名、状态枚举、优先级等

use serde::{Deserialize, Serialize};

// ============================================================
// ID 类型别名
// ============================================================

/// 想法 ID
pub type IdeaId = String;
/// 项目 ID
pub type ProjectId = String;
/// 任务 ID
pub type TaskId = String;
/// 工作流 ID
pub type WorkflowId = String;
/// 节点 ID
pub type NodeId = String;
/// 发布 ID
pub type ReleaseId = String;
/// 分支 ID
pub type BranchId = String;
/// 插件 ID
pub type PluginId = String;
/// 执行 ID(IPC 边界透明序列化为字符串)
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
#[serde(transparent)]
pub struct ExecutionId(String);

impl ExecutionId {
    /// 构造新执行 ID
    pub fn new(s: impl Into<String>) -> Self {
        Self(s.into())
    }
}

impl std::fmt::Display for ExecutionId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl std::ops::Deref for ExecutionId {
    type Target = str;
    fn deref(&self) -> &str {
        &self.0
    }
}

impl From<String> for ExecutionId {
    fn from(s: String) -> Self {
        Self(s)
    }
}

impl From<&str> for ExecutionId {
    fn from(s: &str) -> Self {
        Self(s.to_owned())
    }
}

impl From<ExecutionId> for String {
    fn from(id: ExecutionId) -> Self {
        id.0
    }
}

// ExecutionId 与 &str 的比较(测试/匹配中大量使用)
impl PartialEq<&str> for ExecutionId {
    fn eq(&self, other: &&str) -> bool {
        self.0 == *other
    }
}

impl PartialEq<str> for ExecutionId {
    fn eq(&self, other: &str) -> bool {
        self.0 == other
    }
}

impl PartialEq<String> for ExecutionId {
    fn eq(&self, other: &String) -> bool {
        self.0 == *other
    }
}

/// 决策 ID
pub type DecisionId = String;
/// 节点类型(如 ai / human / ai_self_review)
pub type NodeType = String;
/// 任务链接类型(如 depends_on / blocks / relates_to)
pub type LinkType = String;
/// 工具调用类型(如 function)
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
#[serde(transparent)]
pub struct ToolCallType(String);

impl ToolCallType {
    /// 构造新工具调用类型
    pub fn new(s: impl Into<String>) -> Self {
        Self(s.into())
    }
}

impl std::fmt::Display for ToolCallType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl std::ops::Deref for ToolCallType {
    type Target = str;
    fn deref(&self) -> &str {
        &self.0
    }
}

impl From<String> for ToolCallType {
    fn from(s: String) -> Self {
        Self(s)
    }
}

impl From<&str> for ToolCallType {
    fn from(s: &str) -> Self {
        Self(s.to_owned())
    }
}

impl From<ToolCallType> for String {
    fn from(t: ToolCallType) -> Self {
        t.0
    }
}

// ============================================================
// 时间工具
// ============================================================

/// 当前 Unix 时间戳(毫秒)
///
/// 统一时间获取入口,避免 commands 层与 df-storage 层各写一份 SystemTime 调用(DRY)。
/// 需要字符串形式的调用方自行 `.to_string()`。
pub fn now_millis() -> i64 {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_millis() as i64
}

// ============================================================
// 状态枚举
// ============================================================

/// 想法状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum IdeaStatus {
    /// 草稿
    Draft,
    /// 待评估
    PendingReview,
    /// 已批准
    Approved,
    /// 已拒绝
    Rejected,
    /// 已转为项目
    Promoted,
    /// 已归档
    Archived,
}

impl IdeaStatus {
    /// 返回数据库存储用的小写字符串
    ///
    /// `const fn`(与 TaskStatus::as_str 对齐,允许调用方在 const 上下文使用)。
    pub const fn as_str(&self) -> &'static str {
        match self {
            IdeaStatus::Draft => "draft",
            IdeaStatus::PendingReview => "pending_review",
            IdeaStatus::Approved => "approved",
            IdeaStatus::Rejected => "rejected",
            IdeaStatus::Promoted => "promoted",
            IdeaStatus::Archived => "archived",
        }
    }

    /// 从数据库存储的小写字符串解析为 IdeaStatus(与 `as_str` 对偶)。
    ///
    /// Input Augmentation 层 ProjectResolver/IdeaResolver 把记录的 String status 投影成
    /// 类型化枚举用。未知字符串返 None(调用方按 Draft 兜底或视作数据异常跳过)。
    pub fn from_db_str(s: &str) -> Option<Self> {
        Some(match s {
            "draft" => IdeaStatus::Draft,
            "pending_review" => IdeaStatus::PendingReview,
            "approved" => IdeaStatus::Approved,
            "rejected" => IdeaStatus::Rejected,
            "promoted" => IdeaStatus::Promoted,
            "archived" => IdeaStatus::Archived,
            _ => return None,
        })
    }
}

impl Default for IdeaStatus {
    fn default() -> Self {
        IdeaStatus::Draft
    }
}

/// 项目状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ProjectStatus {
    /// 规划中
    Planning,
    /// 开发中
    InProgress,
    /// 测试中
    Testing,
    /// 发布中
    Releasing,
    /// 已完成
    Completed,
    /// 已暂停
    Paused,
    /// 已取消
    Cancelled,
}

impl ProjectStatus {
    /// 返回数据库存储用的小写字符串
    ///
    /// `const fn`(与 TaskStatus::as_str 对齐,允许调用方在 const 上下文使用)。
    pub const fn as_str(&self) -> &'static str {
        match self {
            ProjectStatus::Planning => "planning",
            ProjectStatus::InProgress => "in_progress",
            ProjectStatus::Testing => "testing",
            ProjectStatus::Releasing => "releasing",
            ProjectStatus::Completed => "completed",
            ProjectStatus::Paused => "paused",
            ProjectStatus::Cancelled => "cancelled",
        }
    }

    /// 从数据库存储的小写字符串解析为 ProjectStatus(与 `as_str` 对偶)。
    ///
    /// Input Augmentation 层 ProjectResolver/TaskResolver 把记录的 String status 投影成
    /// 类型化枚举用。未知字符串返 None。
    pub fn from_db_str(s: &str) -> Option<Self> {
        Some(match s {
            "planning" => ProjectStatus::Planning,
            "in_progress" => ProjectStatus::InProgress,
            "testing" => ProjectStatus::Testing,
            "releasing" => ProjectStatus::Releasing,
            "completed" => ProjectStatus::Completed,
            "paused" => ProjectStatus::Paused,
            "cancelled" => ProjectStatus::Cancelled,
            _ => return None,
        })
    }
}

impl Default for ProjectStatus {
    fn default() -> Self {
        ProjectStatus::Planning
    }
}

/// 任务状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TaskStatus {
    /// 待开始
    Todo,
    /// 进行中
    InProgress,
    /// 代码审查中
    InReview,
    /// 测试中
    Testing,
    /// 已完成
    Done,
    /// 已阻塞
    Blocked,
    /// 已取消
    Cancelled,
}

impl TaskStatus {
    /// 返回数据库存储用的小写字符串
    ///
    /// `const fn` 使调用方可在 `const` 上下文调用(任务 #17 合并:df-nodes 的
    /// `task_state_machine` 字符串常量从本方法派生,消除双源柡移)。
    pub const fn as_str(&self) -> &'static str {
        match self {
            TaskStatus::Todo => "todo",
            TaskStatus::InProgress => "in_progress",
            TaskStatus::InReview => "in_review",
            TaskStatus::Testing => "testing",
            TaskStatus::Done => "done",
            TaskStatus::Blocked => "blocked",
            TaskStatus::Cancelled => "cancelled",
        }
    }

    /// 校验字符串是否为合法的 TaskStatus 存储值（小写 snake_case）。
    /// 用于落库前拦截拼写错误（如 "in-progess"、"in progress"、大小写错等），
    /// 防止任意字符串静默落库导致按枚举查询全漏、任务"消失"。
    pub fn is_valid(s: &str) -> bool {
        matches!(
            s,
            "todo" | "in_progress" | "in_review" | "testing" | "done" | "blocked" | "cancelled"
        )
    }

    /// 合法 status 值列表，用于错误提示。
    pub fn valid_values() -> &'static [&'static str] {
        &[
            "todo",
            "in_progress",
            "in_review",
            "testing",
            "done",
            "blocked",
            "cancelled",
        ]
    }

    /// 从数据库存储的小写字符串解析为 TaskStatus(与 `as_str` 对偶)。
    ///
    /// Input Augmentation 层 TaskResolver 把记录的 String status 投影成类型化枚举用。
    /// 未知字符串返 None。
    pub fn from_db_str(s: &str) -> Option<Self> {
        Some(match s {
            "todo" => TaskStatus::Todo,
            "in_progress" => TaskStatus::InProgress,
            "in_review" => TaskStatus::InReview,
            "testing" => TaskStatus::Testing,
            "done" => TaskStatus::Done,
            "blocked" => TaskStatus::Blocked,
            "cancelled" => TaskStatus::Cancelled,
            _ => return None,
        })
    }
}

impl Default for TaskStatus {
    fn default() -> Self {
        TaskStatus::Todo
    }
}

/// 工作流状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum WorkflowStatus {
    /// 待执行
    Pending,
    /// 运行中
    Running,
    /// 已暂停（等待人工输入等）
    Paused,
    /// 已完成
    Completed,
    /// 已失败
    Failed,
    /// 已取消
    Cancelled,
}

impl WorkflowStatus {
    /// 返回数据库存储用的小写字符串
    pub fn as_str(&self) -> &'static str {
        match self {
            WorkflowStatus::Pending => "pending",
            WorkflowStatus::Running => "running",
            WorkflowStatus::Paused => "paused",
            WorkflowStatus::Completed => "completed",
            WorkflowStatus::Failed => "failed",
            WorkflowStatus::Cancelled => "cancelled",
        }
    }
}

impl Default for WorkflowStatus {
    fn default() -> Self {
        WorkflowStatus::Pending
    }
}

/// 节点状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum NodeStatus {
    /// 待执行
    Pending,
    /// 运行中
    Running,
    /// 已完成
    Completed,
    /// 已失败
    Failed,
    /// 已跳过
    Skipped,
    /// 等待中（如等待人工操作）
    Waiting,
    /// 已取消
    Cancelled,
}

impl NodeStatus {
    /// 返回数据库存储用的小写字符串
    pub fn as_str(&self) -> &'static str {
        match self {
            NodeStatus::Pending => "pending",
            NodeStatus::Running => "running",
            NodeStatus::Completed => "completed",
            NodeStatus::Failed => "failed",
            NodeStatus::Skipped => "skipped",
            NodeStatus::Waiting => "waiting",
            NodeStatus::Cancelled => "cancelled",
        }
    }
}

impl Default for NodeStatus {
    fn default() -> Self {
        NodeStatus::Pending
    }
}

/// 分支状态
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BranchStatus {
    /// 活跃中
    Active,
    /// 已合并
    Merged,
    /// 已废弃
    Abandoned,
}

impl BranchStatus {
    /// 返回数据库存储用的小写字符串
    pub fn as_str(&self) -> &'static str {
        match self {
            BranchStatus::Active => "active",
            BranchStatus::Merged => "merged",
            BranchStatus::Abandoned => "abandoned",
        }
    }
}

impl Default for BranchStatus {
    fn default() -> Self {
        BranchStatus::Active
    }
}

/// 优先级
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Priority {
    /// 低
    Low = 0,
    /// 中
    Medium = 1,
    /// 高
    High = 2,
    /// 紧急
    Critical = 3,
}

impl Priority {
    /// 返回数据库存储用的小写字符串
    pub fn as_str(&self) -> &'static str {
        match self {
            Priority::Low => "low",
            Priority::Medium => "medium",
            Priority::High => "high",
            Priority::Critical => "critical",
        }
    }
}

impl Default for Priority {
    fn default() -> Self {
        Priority::Medium
    }
}

// ============================================================
// 辅助函数
// ============================================================

/// 生成新的 UUID v4 字符串
pub fn new_id() -> String {
    uuid::Uuid::new_v4().to_string()
}

#[cfg(test)]
mod tests {
    use super::TaskStatus;

    // 合法值：覆盖全部枚举变体（与 as_str 一致）
    #[test]
    fn is_valid_accepts_all_variants() {
        assert!(TaskStatus::is_valid("todo"));
        assert!(TaskStatus::is_valid("in_progress"));
        assert!(TaskStatus::is_valid("in_review"));
        assert!(TaskStatus::is_valid("testing"));
        assert!(TaskStatus::is_valid("done"));
        assert!(TaskStatus::is_valid("blocked"));
        assert!(TaskStatus::is_valid("cancelled"));
    }

    // as_str 与 is_valid 必须自洽：每个变体的存储值都应被 is_valid 接受
    #[test]
    fn is_valid_consistent_with_as_str() {
        let all = [
            TaskStatus::Todo,
            TaskStatus::InProgress,
            TaskStatus::InReview,
            TaskStatus::Testing,
            TaskStatus::Done,
            TaskStatus::Blocked,
            TaskStatus::Cancelled,
        ];
        for v in all {
            assert!(
                TaskStatus::is_valid(v.as_str()),
                "as_str({:?}) = {:?} 未被 is_valid 接受",
                v,
                v.as_str()
            );
        }
    }

    // 拼写错误（典型回归场景）
    #[test]
    fn is_valid_rejects_typos() {
        assert!(!TaskStatus::is_valid("in-progess")); // 漏 r + 连字符
        assert!(!TaskStatus::is_valid("in-progress")); // 连字符非下划线
        assert!(!TaskStatus::is_valid("in progress")); // 空格
        assert!(!TaskStatus::is_valid("inprogres")); // 漏 s
        assert!(!TaskStatus::is_valid("tod")); // 截断
        assert!(!TaskStatus::is_valid("don")); // 截断
        assert!(!TaskStatus::is_valid("canceled")); // 美式拼写（单 l）
        assert!(!TaskStatus::is_valid("complete")); // 近义词
        assert!(!TaskStatus::is_valid("pending")); // 近义词
    }

    // 大小写敏感
    #[test]
    fn is_valid_case_sensitive() {
        assert!(!TaskStatus::is_valid("Todo"));
        assert!(!TaskStatus::is_valid("TODO"));
        assert!(!TaskStatus::is_valid("InProgress"));
        assert!(!TaskStatus::is_valid("IN_PROGRESS"));
        assert!(!TaskStatus::is_valid("Done"));
    }

    // 边界：空串、空白、前后空格、带前后缀
    #[test]
    fn is_valid_rejects_empty_and_whitespace() {
        assert!(!TaskStatus::is_valid(""));
        assert!(!TaskStatus::is_valid(" "));
        assert!(!TaskStatus::is_valid(" todo")); // 前导空格
        assert!(!TaskStatus::is_valid("todo ")); // 尾随空格
        assert!(!TaskStatus::is_valid(" todo ")); // 两端空格
        assert!(!TaskStatus::is_valid("todo\n")); // 换行
    }

    // 边界：非 ASCII / 注入尝试
    #[test]
    fn is_valid_rejects_garbage() {
        assert!(!TaskStatus::is_valid("'; DROP TABLE tasks;--"));
        assert!(!TaskStatus::is_valid("待开始")); // 中文近义
        assert!(!TaskStatus::is_valid("todo;done"));
        assert!(!TaskStatus::is_valid("todo,done"));
    }

    // valid_values 必须与 is_valid 自洽（防清单漏项）
    #[test]
    fn valid_values_all_pass_is_valid() {
        for &v in TaskStatus::valid_values() {
            assert!(TaskStatus::is_valid(v), "valid_values 含 {:?} 但 is_valid 拒绝", v);
        }
        // 数量应等于枚举变体数
        assert_eq!(TaskStatus::valid_values().len(), 7);
    }
}
