//! Tauri commands for repository access
//! Uses handle-based system: UUID -> Arc<HybridRepository>
//!
//! TRACES: UR-007, UR-035, UR-036 | JA-004, JA-005, JA-029, JA-030, JA-031

use crate::utils::lock::MutexSafe;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

use log::{debug, error, info, warn};
use serde::{Deserialize, Serialize};
use tauri::{AppHandle, Emitter, State};
use uuid::Uuid;

use crate::jellyfin::HttpClient;
use crate::repository::{
    types::*, HybridRepository, MediaRepository, OfflineRepository, OnlineRepository,
};

/// Repository handle manager
pub struct RepositoryManager {
    repositories: Arc<Mutex<HashMap<String, Arc<HybridRepository>>>>,
}

impl RepositoryManager {
    pub fn new() -> Self {
        Self {
            repositories: Arc::new(Mutex::new(HashMap::new())),
        }
    }

    pub fn create(&self, handle: String, repository: HybridRepository) {
        let mut repos = self.repositories.lock_safe();
        repos.insert(handle, Arc::new(repository));
    }

    pub fn get(&self, handle: &str) -> Option<Arc<HybridRepository>> {
        let repos = self.repositories.lock_safe();
        repos.get(handle).cloned()
    }

    pub fn destroy(&self, handle: &str) {
        let mut repos = self.repositories.lock_safe();
        repos.remove(handle);
    }
}

/// Wrapper for Tauri state
pub struct RepositoryManagerWrapper(pub RepositoryManager);

/// Create a new repository instance
/// Returns a handle (UUID) for accessing the repository
#[tauri::command]
#[specta::specta]
pub async fn repository_create(
    manager: State<'_, RepositoryManagerWrapper>,
    player: State<'_, crate::commands::player::PlayerStateWrapper>,
    db: State<'_, crate::commands::storage::DatabaseWrapper>,
    connectivity: State<'_, crate::commands::connectivity::ConnectivityMonitorWrapper>,
    server_url: String,
    user_id: String,
    access_token: String,
    server_id: String,
) -> Result<String, String> {
    info!("[REPO] repository_create called for user: {}", user_id);

    // Create HTTP client for online repository
    debug!("[REPO] Creating HTTP client...");
    let http_config = crate::jellyfin::HttpConfig::default();
    let http_client = HttpClient::new(http_config).map_err(|e| {
        error!("[REPO] HTTP client creation failed: {}", e);
        e.to_string()
    })?;
    debug!("[REPO] HTTP client created successfully");

    // Grab a connectivity reporter so the online repository's server outcomes
    // drive the reachability state the UI observes (source of truth for the
    // offline/online banner). See docs/architecture/07-connectivity.md.
    let connectivity_reporter = {
        let monitor = connectivity.0.lock().await;
        monitor.reporter()
    };

    // Create online repository wired to connectivity reporting
    debug!("[REPO] Creating online repository...");
    let online = OnlineRepository::new(
        Arc::new(http_client),
        server_url,
        user_id.clone(),
        access_token,
    )
    .with_connectivity(connectivity_reporter);
    debug!("[REPO] Online repository created");

    // Create offline repository with async-safe database service
    debug!("[REPO] Creating database service...");
    let db_service = {
        let database = db.0.lock().map_err(|e| {
            error!("[REPO] Database lock failed: {}", e);
            e.to_string()
        })?;
        debug!("[REPO] Database lock acquired, getting service...");
        Arc::new(database.service())
    }; // Lock is released here
    debug!("[REPO] Database service created");

    debug!("[REPO] Creating offline repository...");
    let offline = OfflineRepository::new(db_service, server_id, user_id);
    debug!("[REPO] Offline repository created");

    // Create hybrid repository
    debug!("[REPO] Creating hybrid repository...");
    let hybrid = HybridRepository::new(online, offline);
    debug!("[REPO] Hybrid repository created");

    // Generate handle and store repository
    let uuid = Uuid::new_v4();
    let handle = format!("{}", uuid);
    info!("[REPO] Generated handle: {}", handle);

    // Store repository synchronously
    debug!("[REPO] Storing repository...");
    manager.0.create(handle.clone(), hybrid);
    info!("[REPO] Repository stored successfully");

    // Give the player controller a repository for next-episode lookups. The
    // Android playback-ended callback has no repository handle, so without
    // this the episode autoplay countdown never triggers there.
    if let Some(repo) = manager.0.get(&handle) {
        let controller = player.0.lock().await;
        controller.set_repository(repo);
    }

    Ok(handle)
}

/// Destroy a repository instance
#[tauri::command]
#[specta::specta]
pub async fn repository_destroy(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
) -> Result<(), String> {
    manager.0.destroy(&handle);
    Ok(())
}

/// Get libraries
#[tauri::command]
#[specta::specta]
pub async fn repository_get_libraries(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
) -> Result<Vec<Library>, String> {
    debug!("[REPO] get_libraries called with handle: {}", handle);
    let repo = manager.0.get(&handle).ok_or_else(|| {
        error!("[REPO] Repository not found for handle: {}", handle);
        "Repository not found".to_string()
    })?;
    debug!("[REPO] Repository found, fetching libraries...");
    repo.as_ref().get_libraries().await.map_err(|e| {
        error!("[REPO] Error fetching libraries: {:?}", e);
        format!("{:?}", e)
    })
}

/// Get items in a container (library, folder, album, etc.)
#[tauri::command]
#[specta::specta]
pub async fn repository_get_items(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    parent_id: String,
    options: Option<GetItemsOptions>,
) -> Result<SearchResult, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_items(&parent_id, options)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get a single item by ID
#[tauri::command]
#[specta::specta]
pub async fn repository_get_item(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
) -> Result<MediaItem, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_item(&item_id)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Downloaded-only browse: libraries that contain downloaded content.
///
/// Backs the Downloads "Downloaded" surface. Never merges server results and is
/// authoritative — an empty list means nothing is downloaded.
///
/// TRACES: UR-055 | DR-082
#[tauri::command]
#[specta::specta]
pub async fn repository_get_downloaded_libraries(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
) -> Result<Vec<Library>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.get_downloaded_libraries()
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Downloaded-only browse: items under a container that are on the device.
///
/// TRACES: UR-055 | DR-082, DR-083
#[tauri::command]
#[specta::specta]
pub async fn repository_get_downloaded_items(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    parent_id: String,
    options: Option<GetItemsOptions>,
) -> Result<SearchResult, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.get_downloaded_items(&parent_id, options)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// On-disk usage of downloaded content (device total, per-item/container bytes).
///
/// TRACES: UR-056 | DR-085
#[tauri::command]
#[specta::specta]
pub async fn repository_get_download_disk_usage(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
) -> Result<DownloadDiskUsage, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.get_download_disk_usage()
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Query the optional JRay plugin for the actors on screen at time `t`
/// (seconds) in an item. Returns an empty list when JRay isn't installed or
/// has no data for the item, so the caller can render nothing without error.
#[tauri::command]
#[specta::specta]
pub async fn repository_jray_actors_at(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    t: f64,
) -> Result<Vec<crate::repository::JRayActor>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_jray_actors(&item_id, t)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get latest items in a library
#[tauri::command]
#[specta::specta]
pub async fn repository_get_latest_items(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    parent_id: String,
    limit: Option<usize>,
) -> Result<Vec<MediaItem>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_latest_items(&parent_id, limit)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get resume items (continue watching/listening)
#[tauri::command]
#[specta::specta]
pub async fn repository_get_resume_items(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    parent_id: Option<String>,
    limit: Option<usize>,
) -> Result<Vec<MediaItem>, String> {
    debug!("[REPO] get_resume_items called with handle: {}", handle);
    let repo = manager.0.get(&handle).ok_or_else(|| {
        error!("[REPO] Repository not found for handle: {}", handle);
        "Repository not found".to_string()
    })?;
    debug!("[REPO] Repository found, fetching resume items...");
    repo.as_ref()
        .get_resume_items(parent_id.as_deref(), limit)
        .await
        .map_err(|e| {
            error!("[REPO] Error fetching resume items: {:?}", e);
            format!("{:?}", e)
        })
}

/// Get next up episodes
#[tauri::command]
#[specta::specta]
pub async fn repository_get_next_up_episodes(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    series_id: Option<String>,
    limit: Option<usize>,
) -> Result<Vec<MediaItem>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_next_up_episodes(series_id.as_deref(), limit)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get recently played audio
#[tauri::command]
#[specta::specta]
pub async fn repository_get_recently_played_audio(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    limit: Option<usize>,
) -> Result<Vec<MediaItem>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_recently_played_audio(limit)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get resume movies
#[tauri::command]
#[specta::specta]
pub async fn repository_get_resume_movies(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    limit: Option<usize>,
) -> Result<Vec<MediaItem>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_resume_movies(limit)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get albums the user hasn't listened to recently ("rediscover")
#[tauri::command]
#[specta::specta]
pub async fn repository_get_rediscover_albums(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    parent_id: Option<String>,
    limit: Option<usize>,
) -> Result<Vec<MediaItem>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_rediscover_albums(parent_id.as_deref(), limit)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get genres for a library
#[tauri::command]
#[specta::specta]
pub async fn repository_get_genres(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    parent_id: Option<String>,
) -> Result<Vec<Genre>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_genres(parent_id.as_deref())
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Tauri event name carrying the merged (cache + server) search results.
pub const SEARCH_EVENT_NAME: &str = "search-event";

/// Payload for the deferred, merged search results pushed to the frontend.
///
/// `request_id` matches the value the frontend passed to `repository_search`,
/// letting it discard updates from queries that have since been superseded.
#[derive(specta::Type, Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SearchUpdateEvent {
    pub request_id: u32,
    pub result: SearchResult,
}

/// Search for items
#[tauri::command]
#[specta::specta]
pub async fn repository_search(
    app: AppHandle,
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    query: String,
    options: Option<SearchOptions>,
    request_id: u32,
) -> Result<SearchResult, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;

    // Phase 1: instant local results from the cache (downloaded content) so the
    // UI can render immediately while the server is still being queried.
    let cache_result = repo
        .search_cache_only(&query, options.clone())
        .await
        .unwrap_or_else(|e| {
            debug!("[Search] Cache search miss/timeout: {:?}", e);
            SearchResult {
                items: Vec::new(),
                total_record_count: 0,
            }
        });

    // Phase 2: query the live server in the background, merge with the cache,
    // and push the union to the frontend via a `search-event`. Tagged with
    // `request_id` so the frontend can discard results from superseded queries.
    let repo_bg = repo.clone();
    let cache_for_merge = cache_result.clone();
    tauri::async_runtime::spawn(async move {
        match repo_bg.search_server_only(&query, options).await {
            Ok(server_result) => {
                let merged = HybridRepository::merge_search_results(cache_for_merge, server_result);
                let event = SearchUpdateEvent {
                    request_id,
                    result: merged,
                };
                if let Err(e) = app.emit(SEARCH_EVENT_NAME, &event) {
                    error!("[Search] Failed to emit search update: {}", e);
                }
            }
            Err(e) => {
                // Server failed — the cache results are already on screen, so
                // just log. (Offline / unreachable server falls here.)
                warn!(
                    "[Search] Server search failed, keeping cache results: {:?}",
                    e
                );
            }
        }
    });

    Ok(cache_result)
}

/// Get playback info for an item
#[tauri::command]
#[specta::specta]
pub async fn repository_get_playback_info(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
) -> Result<PlaybackInfo, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_playback_info(&item_id)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get video stream URL with optional seeking support
#[tauri::command]
#[specta::specta]
pub async fn repository_get_video_stream_url(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    media_source_id: Option<String>,
    start_time_seconds: Option<f64>,
    audio_stream_index: Option<i32>,
) -> Result<String, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_video_stream_url(
            &item_id,
            media_source_id.as_deref(),
            start_time_seconds,
            audio_stream_index,
        )
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get an audio-only stream URL for a *video* item (background-audio handoff).
///
/// TRACES: UR-040 | JA-032 | UT-061
#[tauri::command]
#[specta::specta]
pub async fn repository_get_audio_only_stream_url_for_video(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    media_source_id: Option<String>,
    start_time_seconds: Option<f64>,
    audio_stream_index: Option<i32>,
) -> Result<String, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_audio_only_stream_url_for_video(
            &item_id,
            media_source_id.as_deref(),
            start_time_seconds,
            audio_stream_index,
        )
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get audio stream URL for a track
#[tauri::command]
#[specta::specta]
pub async fn repository_get_audio_stream_url(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
) -> Result<String, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_audio_stream_url(&item_id)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get Live TV channels (broadcast / IPTV) for browsing
#[tauri::command]
#[specta::specta]
pub async fn repository_get_live_tv_channels(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
) -> Result<Vec<MediaItem>, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_live_tv_channels()
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get the root list of plugin "Channels"
#[tauri::command]
#[specta::specta]
pub async fn repository_get_channels(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
) -> Result<SearchResult, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_channels()
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Open a live stream for a Live TV channel / live item
#[tauri::command]
#[specta::specta]
pub async fn repository_open_live_stream(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
) -> Result<LiveStreamInfo, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .open_live_stream(&item_id)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Report playback start
#[tauri::command]
#[specta::specta]
pub async fn repository_report_playback_start(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    position_ticks: i64,
) -> Result<(), String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .report_playback_start(&item_id, position_ticks)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Report playback progress
#[tauri::command]
#[specta::specta]
pub async fn repository_report_playback_progress(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    position_ticks: i64,
) -> Result<(), String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .report_playback_progress(&item_id, position_ticks)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Report playback stopped
#[tauri::command]
#[specta::specta]
pub async fn repository_report_playback_stopped(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    position_ticks: i64,
) -> Result<(), String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .report_playback_stopped(&item_id, position_ticks)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get image URL for an item
#[tauri::command]
#[specta::specta]
pub fn repository_get_image_url(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    image_type: ImageType,
    options: Option<ImageOptions>,
) -> Result<String, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    Ok(repo.as_ref().get_image_url(&item_id, image_type, options))
}

/// Get subtitle URL for a media item
#[tauri::command]
#[specta::specta]
#[allow(dead_code)]
pub fn repository_get_subtitle_url(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    media_source_id: String,
    stream_index: i32,
    format: String,
) -> Result<String, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    Ok(repo
        .as_ref()
        .get_subtitle_url(&item_id, &media_source_id, stream_index, &format))
}

/// Get video download URL with quality preset
#[tauri::command]
#[specta::specta]
#[allow(dead_code)]
pub fn repository_get_video_download_url(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    quality: String,
    media_source_id: Option<String>,
) -> Result<String, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    Ok(repo
        .as_ref()
        .get_video_download_url(&item_id, &quality, media_source_id.as_deref()))
}

/// Mark an item as favorite
#[tauri::command]
#[specta::specta]
pub async fn repository_mark_favorite(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
) -> Result<(), String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .mark_favorite(&item_id)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Unmark an item as favorite
#[tauri::command]
#[specta::specta]
pub async fn repository_unmark_favorite(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
) -> Result<(), String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .unmark_favorite(&item_id)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get person details
#[tauri::command]
#[specta::specta]
pub async fn repository_get_person(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    person_id: String,
) -> Result<MediaItem, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_person(&person_id)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get items by person (actor, director, etc.)
#[tauri::command]
#[specta::specta]
pub async fn repository_get_items_by_person(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    person_id: String,
    options: Option<GetItemsOptions>,
) -> Result<SearchResult, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_items_by_person(&person_id, options)
        .await
        .map_err(|e| format!("{:?}", e))
}

/// Get similar/related items for a media item
#[tauri::command]
#[specta::specta]
pub async fn repository_get_similar_items(
    manager: State<'_, RepositoryManagerWrapper>,
    handle: String,
    item_id: String,
    limit: Option<usize>,
) -> Result<SearchResult, String> {
    let repo = manager.0.get(&handle).ok_or("Repository not found")?;
    repo.as_ref()
        .get_similar_items(&item_id, limit)
        .await
        .map_err(|e| format!("{:?}", e))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_repository_manager_creation() {
        let manager = RepositoryManager::new();
        // A freshly created manager holds no repositories
        assert!(manager.get("any-handle").is_none());
    }

    #[test]
    fn test_repository_manager_wrapper_structure() {
        let manager = RepositoryManager::new();
        let wrapper = RepositoryManagerWrapper(manager);
        // The wrapper exposes the underlying manager, which starts empty
        assert!(wrapper.0.get("any-handle").is_none());
    }

    #[test]
    fn test_repository_manager_get_nonexistent() {
        let manager = RepositoryManager::new();
        // Getting a non-existent repository should return None
        let result = manager.get("nonexistent-handle");
        assert!(result.is_none());
    }

    #[test]
    fn test_uuid_handle_generation() {
        let uuid = Uuid::new_v4();
        let handle = format!("{}", uuid);
        // UUID should convert to a non-empty string
        assert!(!handle.is_empty());
        assert!(handle.len() > 0);
    }

    #[test]
    fn test_uuid_handles_are_unique() {
        let handle1 = format!("{}", Uuid::new_v4());
        let handle2 = format!("{}", Uuid::new_v4());
        // Two generated UUIDs should be different
        assert_ne!(handle1, handle2);
    }

    #[test]
    fn test_uuid_handle_format() {
        let uuid = Uuid::new_v4();
        let handle = format!("{}", uuid);
        // UUID should have standard format with hyphens
        let parts: Vec<&str> = handle.split('-').collect();
        assert_eq!(parts.len(), 5);
    }

    #[test]
    fn test_repository_manager_destroy_nonexistent() {
        let manager = RepositoryManager::new();
        // Destroying a non-existent repository should not panic
        manager.destroy("nonexistent-handle");
    }

    #[test]
    fn test_repository_manager_is_send_sync() {
        // Verify RepositoryManager can be used in async contexts
        fn is_send_sync<T: Send + Sync>() {}
        is_send_sync::<RepositoryManager>();
    }

    #[test]
    fn test_repository_manager_wrapper_is_send_sync() {
        // Verify RepositoryManagerWrapper is Send + Sync
        fn is_send_sync<T: Send + Sync>() {}
        is_send_sync::<RepositoryManagerWrapper>();
    }

    #[test]
    fn test_multiple_manager_instances() {
        let manager1 = RepositoryManager::new();
        let manager2 = RepositoryManager::new();

        // Multiple manager instances should be independent
        let handle1_nonexistent = manager1.get("test");
        let handle2_nonexistent = manager2.get("test");

        assert!(handle1_nonexistent.is_none());
        assert!(handle2_nonexistent.is_none());
    }

    #[test]
    fn test_handle_string_properties() {
        let uuid = Uuid::new_v4();
        let handle = format!("{}", uuid);

        // Handle should be alphanumeric with hyphens
        for c in handle.chars() {
            assert!(c.is_alphanumeric() || c == '-');
        }
    }

    #[test]
    fn test_repository_manager_concurrent_access() {
        let manager = Arc::new(RepositoryManager::new());
        let mut handles = vec![];

        // Verify manager can be wrapped in Arc for concurrent access
        for _ in 0..3 {
            let mgr = Arc::clone(&manager);
            let handle = std::thread::spawn(move || {
                let result = mgr.get("test");
                assert!(result.is_none());
            });
            handles.push(handle);
        }

        for h in handles {
            h.join().unwrap();
        }
    }
}
