use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use uuid::Uuid;
use validator::Validate;

// --- 流程图节点/边定义 ---

/// BPMN 节点类型
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, PartialEq)]
pub enum NodeType {
    StartEvent,
    EndEvent,
    UserTask,
    ServiceTask,
    ExclusiveGateway,
    ParallelGateway,
}

/// 流程图节点定义
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct NodeDef {
    pub id: String,
    #[serde(rename = "type")]
    pub node_type: NodeType,
    pub name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub assignee_id: Option<Uuid>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub candidate_groups: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub service_type: Option<String>,
    /// 服务任务 HTTP 调用配置
    #[serde(skip_serializing_if = "Option::is_none")]
    pub service_config: Option<ServiceTaskConfig>,
    /// 前端渲染位置
    #[serde(skip_serializing_if = "Option::is_none")]
    pub position: Option<NodePosition>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct NodePosition {
    pub x: f64,
    pub y: f64,
}

/// ServiceTask HTTP 调用配置
#[derive(Debug, Clone, Serialize, Deserialize, Validate, ToSchema)]
pub struct ServiceTaskConfig {
    /// 请求 URL（仅允许 http/https 协议，禁止内网地址）
    #[validate(length(min = 1, max = 2048), custom(function = "validate_service_url"))]
    pub url: String,
    /// HTTP 方法（GET / POST），默认 GET
    #[serde(default = "default_method")]
    #[validate(custom(function = "validate_http_method"))]
    pub method: String,
    /// POST body 模板（支持从流程变量替换 ${var_name}）
    #[serde(skip_serializing_if = "Option::is_none")]
    pub body: Option<serde_json::Value>,
}

fn default_method() -> String {
    "GET".to_string()
}

fn validate_service_url(value: &str) -> Result<(), validator::ValidationError> {
    if !value.starts_with("https://") && !value.starts_with("http://") {
        return Err(validator::ValidationError::new("invalid_url_scheme"));
    }
    if value.contains("127.0.0.1") || value.contains("localhost") || value.contains("0.0.0.0") {
        return Err(validator::ValidationError::new("ssrf_blocked"));
    }
    Ok(())
}

fn validate_http_method(value: &str) -> Result<(), validator::ValidationError> {
    match value {
        "GET" | "POST" => Ok(()),
        _ => Err(validator::ValidationError::new("invalid_http_method")),
    }
}

/// 流程图连线定义
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct EdgeDef {
    pub id: String,
    pub source: String,
    pub target: String,
    /// 条件表达式（排他网关分支）
    #[serde(skip_serializing_if = "Option::is_none")]
    pub condition: Option<String>,
    /// 前端渲染标签
    #[serde(skip_serializing_if = "Option::is_none")]
    pub label: Option<String>,
}

/// 完整流程图
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct FlowDiagram {
    pub nodes: Vec<NodeDef>,
    pub edges: Vec<EdgeDef>,
}

// --- 流程定义 DTOs ---

#[derive(Debug, Serialize, ToSchema)]
pub struct ProcessDefinitionResp {
    pub id: Uuid,
    pub name: String,
    pub key: String,
    pub version: i32,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub category: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    pub nodes: serde_json::Value,
    pub edges: serde_json::Value,
    pub status: String,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub lock_version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct CreateProcessDefinitionReq {
    #[validate(length(min = 1, max = 200, message = "流程名称不能为空"))]
    pub name: String,
    #[validate(length(min = 1, max = 100, message = "流程编码不能为空"))]
    pub key: String,
    pub category: Option<String>,
    pub description: Option<String>,
    pub nodes: Vec<NodeDef>,
    pub edges: Vec<EdgeDef>,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct UpdateProcessDefinitionReq {
    #[validate(length(max = 200, message = "流程名称过长"))]
    pub name: Option<String>,
    pub category: Option<String>,
    pub description: Option<String>,
    pub nodes: Option<Vec<NodeDef>>,
    pub edges: Option<Vec<EdgeDef>>,
    pub version: i32,
}

// --- 流程实例 DTOs ---

#[derive(Debug, Serialize, ToSchema)]
pub struct ProcessInstanceResp {
    pub id: Uuid,
    pub definition_id: Uuid,
    pub definition_name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub business_key: Option<String>,
    pub status: String,
    pub started_by: Uuid,
    pub started_at: DateTime<Utc>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub completed_at: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
    /// 当前活跃的 token 位置
    pub active_tokens: Vec<TokenResp>,
    pub version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct StartInstanceReq {
    pub definition_id: Uuid,
    pub business_key: Option<String>,
    /// 初始流程变量
    pub variables: Option<Vec<SetVariableReq>>,
}

// --- Token DTOs ---

#[derive(Debug, Serialize, ToSchema)]
pub struct TokenResp {
    pub id: Uuid,
    pub node_id: String,
    pub status: String,
    pub created_at: DateTime<Utc>,
}

// --- 任务 DTOs ---

#[derive(Debug, Serialize, ToSchema)]
pub struct TaskResp {
    pub id: Uuid,
    pub instance_id: Uuid,
    pub token_id: Uuid,
    pub node_id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub node_name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub assignee_id: Option<Uuid>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub candidate_groups: Option<serde_json::Value>,
    pub status: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub outcome: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub form_data: Option<serde_json::Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub due_date: Option<DateTime<Utc>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub completed_at: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
    /// 流程定义名称（用于列表展示）
    #[serde(skip_serializing_if = "Option::is_none")]
    pub definition_name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub business_key: Option<String>,
    pub version: i32,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct CompleteTaskReq {
    #[validate(length(min = 1, max = 50, message = "审批结果不能为空"))]
    pub outcome: String,
    pub form_data: Option<serde_json::Value>,
}

#[derive(Debug, Deserialize, Validate, ToSchema)]
pub struct DelegateTaskReq {
    pub delegate_to: Uuid,
}

// --- 流程变量 DTOs ---

#[derive(Debug, Serialize, ToSchema)]
pub struct ProcessVariableResp {
    pub id: Uuid,
    pub name: String,
    pub var_type: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub value_string: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub value_number: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub value_boolean: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub value_date: Option<DateTime<Utc>>,
}

#[derive(Debug, Clone, Deserialize, Validate, ToSchema)]
pub struct SetVariableReq {
    #[validate(length(min = 1, max = 100, message = "变量名不能为空"))]
    pub name: String,
    pub var_type: Option<String>,
    pub value: serde_json::Value,
}
