use uuid::Uuid;
use service_kit::api_dto;
use crate::subjects::{NatsSubject, SubjectMessage};

// --- Enums ---

#[api_dto]
#[derive(Copy, PartialEq, Eq, Hash)]
pub enum WorkflowStatus {
    Pending,
    Running,
    Completed,
    Failed,
    Cancelled,
}

#[api_dto]
#[derive(Copy, PartialEq, Eq, Hash)]
pub enum TaskStatus {
    Pending,
    Scheduled,
    Running,
    Completed,
    Failed,
    Skipped,
    Cancelled,
}

// --- Data Structures ---

/// Context information required for a worker to execute a task.
/// This tells the worker "where" to work (Git Commit).
#[api_dto]
pub struct TaskContext {
    /// The Git commit hash that this task should base its work on.
    /// If None/Empty, it implies starting from an empty repo (or initial state).
    pub base_commit: Option<String>,
    
    /// Suggested path where the worker should mount/write its output.
    /// This is a hint; strict adherence depends on the worker implementation.
    pub mount_path: Option<String>,
}

/// Configuration related to storage access.
#[api_dto]
pub struct StorageConfig {
    /// The root path on the host/container where the shared volume is mounted.
    /// e.g., "/mnt/workflow_data"
    pub root_path: String,
}

// --- Commands ---

/// A generic command sent by the Orchestrator to a Worker.
/// The `routing_key` in the subject determines which worker receives it.
#[api_dto]
pub struct WorkflowTaskCommand {
    pub request_id: Uuid,
    pub task_id: String,
    pub routing_key: String,
    
    /// Dynamic configuration specific to the worker (e.g., {"market": "CN", "years": 5}).
    /// The worker is responsible for parsing this.
    pub config: serde_json::Value,
    
    pub context: TaskContext,
    pub storage: StorageConfig,
}

impl SubjectMessage for WorkflowTaskCommand {
    fn subject(&self) -> NatsSubject {
        // The actual subject is dynamic based on routing_key.
        // This return value is primarily for default behavior or matching.
        NatsSubject::WorkflowCommand(self.routing_key.clone())
    }
}

// --- Events ---

/// A generic event sent by a Worker back to the Orchestrator upon task completion (or failure).
#[api_dto]
pub struct WorkflowTaskEvent {
    pub request_id: Uuid,
    pub task_id: String,
    pub status: TaskStatus,
    
    /// The result of the task execution.
    pub result: Option<TaskResult>,
}

impl SubjectMessage for WorkflowTaskEvent {
    fn subject(&self) -> NatsSubject {
        NatsSubject::WorkflowEventTaskCompleted
    }
}

#[api_dto]
pub struct TaskResult {
    /// The new Git commit hash generated by this task.
    /// Should be None if the task failed.
    pub new_commit: Option<String>,
    
    /// Error message if the task failed.
    pub error: Option<String>,
    
    /// Optional metadata or summary of the result (not the full data).
    pub summary: Option<serde_json::Value>,
}

