//! Data Transfer Objects for API key management (P4.2 Authentication).

use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

/// Request to create a new API key.
#[derive(Debug, Clone, Deserialize, ToSchema)]
pub struct CreateApiKeyRequest {
    /// Environment: "live" or "test".
    pub environment: String,
    /// Role: "read_only", "write_agent", or "admin".
    pub role: String,
    /// Human-readable label for this key.
    pub label: String,
    /// Optional rate limit (requests per hour). Defaults to 10,000.
    #[serde(default)]
    pub rate_limit: Option<u64>,
    /// Optional expiration timestamp (Unix epoch seconds).
    #[serde(default)]
    pub expires_at: Option<u64>,
}

/// Response after creating a new API key.
///
/// **IMPORTANT**: The `key` field contains the raw API key and is only returned once.
/// Store it securely - it cannot be retrieved later.
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct CreateApiKeyResponse {
    /// The raw API key. **Store this securely - it cannot be retrieved later.**
    pub key: String,
    /// First 12 characters of the key for identification.
    pub key_prefix: String,
    /// Hex-encoded BLAKE3 hash of the key.
    pub key_hash: String,
    /// Role assigned to this key.
    pub role: String,
    /// Human-readable label.
    pub label: String,
    /// Rate limit (requests per hour).
    pub rate_limit: u64,
    /// Expiration timestamp if set.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub expires_at: Option<u64>,
}

/// Information about an existing API key.
///
/// Note: The raw key is not included - only the hash and prefix are available.
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct ApiKeyInfo {
    /// Hex-encoded BLAKE3 hash of the key.
    pub key_hash: String,
    /// First 12 characters of the key for identification.
    pub key_prefix: String,
    /// Role assigned to this key.
    pub role: String,
    /// Human-readable label.
    pub label: String,
    /// Rate limit (requests per hour).
    pub rate_limit: u64,
    /// Unix timestamp when the key was created.
    pub created_at: u64,
    /// Unix timestamp when the key was last used.
    pub last_used_at: u64,
    /// Expiration timestamp if set.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub expires_at: Option<u64>,
    /// Whether the key is currently enabled.
    pub enabled: bool,
}

/// Response listing all API keys.
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct ListApiKeysResponse {
    /// List of API key records.
    pub keys: Vec<ApiKeyInfo>,
    /// Total number of keys.
    pub total: usize,
}

/// Response after revoking an API key.
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct RevokeApiKeyResponse {
    /// Whether the key was successfully revoked.
    pub revoked: bool,
    /// Hex-encoded hash of the revoked key.
    pub key_hash: String,
}

/// Response after rotating an API key.
///
/// **IMPORTANT**: The `new_key` field contains the new raw API key and is only returned once.
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct RotateApiKeyResponse {
    /// The new raw API key. **Store this securely - it cannot be retrieved later.**
    pub new_key: String,
    /// First 12 characters of the new key.
    pub new_key_prefix: String,
    /// Hex-encoded hash of the new key.
    pub new_key_hash: String,
    /// Hex-encoded hash of the old (revoked) key.
    pub old_key_hash: String,
    /// Role preserved from the old key.
    pub role: String,
    /// Label preserved from the old key.
    pub label: String,
}

/// Request to update an API key's enabled status.
#[derive(Debug, Clone, Deserialize, ToSchema)]
pub struct UpdateApiKeyRequest {
    /// New enabled state.
    pub enabled: bool,
}

/// Response after updating an API key.
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct UpdateApiKeyResponse {
    /// Whether the update was successful.
    pub updated: bool,
    /// Hex-encoded hash of the updated key.
    pub key_hash: String,
    /// New enabled state.
    pub enabled: bool,
}

impl From<stemedb_storage::ApiKeyRecord> for ApiKeyInfo {
    fn from(record: stemedb_storage::ApiKeyRecord) -> Self {
        Self {
            key_hash: hex::encode(record.key_hash),
            key_prefix: record.key_prefix,
            role: record.role.as_str().to_string(),
            label: record.label,
            rate_limit: record.rate_limit.unwrap_or(stemedb_storage::DEFAULT_API_KEY_RATE_LIMIT),
            created_at: record.created_at,
            last_used_at: record.last_used_at,
            expires_at: record.expires_at,
            enabled: record.enabled,
        }
    }
}
