use serde::{Deserialize, Serialize};
use std::time::Duration;
use thiserror::Error;
#[derive(Debug, Error)]
#[allow(clippy::enum_variant_names)]
pub enum CloudSyncError {
#[error("Authentication failed: {0}")]
AuthenticationError(String),
#[error("Rate limit exceeded. Retrying in {retry_after}s (attempt {attempt}/3)")]
RateLimitError { retry_after: u64, attempt: u32 },
#[error("Server error: {status} - {message}")]
ServerError { status: u16, message: String },
#[error("Network error: {0}")]
#[allow(dead_code)]
NetworkError(String),
#[error("Validation failed in {file}:{line} - {reason}")]
#[allow(dead_code)]
ValidationError {
file: String,
line: usize,
reason: String,
},
#[error("Configuration error: {0}")]
ConfigError(String),
#[error("API error: {0}")]
ApiError(String),
}
#[derive(Debug, Deserialize)]
pub struct GetTableEntriesResponse {
#[serde(alias = "entries", alias = "data")]
pub entries: Vec<LocalizationEntry>,
#[serde(skip_serializing_if = "Option::is_none", alias = "nextPageCursor")]
#[allow(dead_code)]
pub next_cursor: Option<String>,
}
#[derive(Debug, Serialize)]
#[allow(dead_code)]
pub struct UpdateTableRequest {
pub entries: Vec<LocalizationEntry>,
}
#[derive(Debug, Deserialize)]
#[allow(dead_code)]
pub struct ListTablesResponse {
pub data: Vec<TableInfo>,
}
#[derive(Debug, Deserialize)]
#[allow(dead_code)]
pub struct TableInfo {
pub id: String,
pub name: Option<String>,
#[serde(rename = "ownerType")]
pub owner_type: Option<String>,
#[serde(rename = "ownerId")]
pub owner_id: Option<i64>,
#[serde(rename = "assetId")]
pub asset_id: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LocalizationEntry {
pub identifier: Identifier,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<EntryMetadata>,
pub translations: Vec<Translation>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Identifier {
pub key: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub context: Option<String>,
pub source: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EntryMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub example: Option<String>,
#[serde(rename = "entryType", skip_serializing_if = "Option::is_none")]
pub entry_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Translation {
pub locale: String,
#[serde(rename = "translationText")]
pub translation_text: String,
}
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct CloudConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub table_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub game_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub api_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub strategy: Option<String>,
}
#[derive(Debug)]
pub struct UploadStats {
pub entries_uploaded: usize,
pub locales_processed: usize,
pub duration: Duration,
}
#[derive(Debug)]
pub struct DownloadStats {
pub entries_downloaded: usize,
pub locales_created: usize,
pub locales_updated: usize,
pub duration: Duration,
}
#[derive(Debug)]
pub struct SyncStats {
pub entries_added: usize,
pub entries_updated: usize,
pub entries_deleted: usize,
pub conflicts_skipped: usize,
pub duration: Duration,
}