//! Reservation type - represents a credit hold (2-phase commit)

use chrono::{DateTime, Duration, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

/// Reservation represents a credit hold (2-phase commit)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Reservation {
    /// Unique reservation ID
    pub id: String,
    /// Project ID
    pub project_id: String,
    /// Reserved amount
    pub amount: i64,
    /// Reservation status
    pub status: ReservationStatus,
    /// Description
    pub description: String,
    /// Expiration timestamp
    pub expires_at: DateTime<Utc>,
    /// Creation timestamp
    pub created_at: DateTime<Utc>,
}

impl Reservation {
    /// Create a new reservation
    pub fn new(project_id: String, amount: i64, description: String, ttl_seconds: i64) -> Self {
        let now = Utc::now();
        Self {
            id: Uuid::new_v4().to_string(),
            project_id,
            amount,
            status: ReservationStatus::Pending,
            description,
            expires_at: now + Duration::seconds(ttl_seconds),
            created_at: now,
        }
    }

    /// Check if reservation is expired
    pub fn is_expired(&self) -> bool {
        Utc::now() > self.expires_at
    }

    /// Check if reservation can be committed
    pub fn can_commit(&self) -> bool {
        self.status == ReservationStatus::Pending && !self.is_expired()
    }
}

/// Reservation status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Default)]
pub enum ReservationStatus {
    /// Reservation is pending
    #[default]
    Pending,
    /// Reservation has been committed
    Committed,
    /// Reservation has been released
    Released,
    /// Reservation has expired
    Expired,
}

