use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MainResult {
    pub name: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CloudJobDict {
    pub public_id: Option<String>,
    pub compute_node_url: Option<String>,
    pub started_at: Option<String>,
    pub finished_at: Option<String>,
    pub error_code: Option<i32>,
    pub reserved_cpu_in_nano_shares: Option<i64>,
    pub reserved_gpu_count: Option<i32>,
    pub reserved_memory_in_bytes: Option<i64>,
    pub max_runtime_in_seconds: Option<i32>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobDict {
    pub uuid: String,
    pub auth_token: String,
    pub app_uri: Option<String>,
    pub state: Option<String>,
    pub created_at: Option<String>,
    pub started_at: Option<String>,
    pub ended_at: Option<String>,
    pub cloud_job: Option<CloudJobDict>,
    pub main_result: Option<MainResult>,
    pub arguments_override_command: Option<bool>,
    pub requested_machine: Option<String>,
    #[serde(alias = "public_id")]
    pub _public_id: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreatedJobDict {
    pub uuid: String,
    pub auth_token: String,
    pub public_id: String,
    #[serde(flatten)]
    pub extra: serde_json::Value,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CloudJobCreatedResponse {
    pub public_id: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobStatusResponse {
    pub is_completed: bool,
    #[serde(default)]
    pub status_updates: Vec<StatusUpdate>,
    #[serde(default)]
    pub stdout_and_stderr_packages_b64: Vec<String>,
    #[serde(default)]
    pub previous_status_updates: Vec<StatusUpdate>,
    #[serde(default)]
    pub streamed_logs_packages_b64: Vec<String>,
    pub error_code: Option<i32>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatusUpdate {
    pub log_message: String,
    pub progress: Option<i32>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobsPaginatedResponse {
    pub results: Vec<JobDict>,
    pub page_count: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PresignedDownloadResponse {
    pub presigned_download_url: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PresignedUploadResponse {
    pub presigned_upload_url: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserInfo {
    pub email: String,
    pub account: UserAccount,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserAccount {
    pub display_name: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TokenExchangeResponse {
    pub access_token: String,
    pub refresh_token: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TokenRefreshResponse {
    pub access: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExperimentDict {
    pub uuid: String,
    pub name: String,
    pub uri: Option<String>,
    pub created_at: Option<String>,
    pub job_count: Option<u64>,
    pub job_running_count: Option<u64>,
    pub experiment: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceDetailedDict {
    pub uuid: String,
    pub name: String,
    pub uri: String,
    pub created_at: Option<String>,
    pub experiment: Option<serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExperimentsPaginatedResponse {
    pub results: Vec<ExperimentDict>,
    pub page_count: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExperimentCreateResponse {
    pub uuid: String,
}
