//! Storage migration tools for seamless backend transitions
//!
//! This module provides comprehensive migration capabilities for moving data
//! between different storage backends while maintaining data integrity and
//! providing detailed progress reporting.

use std::collections::HashMap;
use std::sync::Arc;
use std::time::Instant;

use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
use tracing::{debug, error, info, warn};
use uuid::Uuid;

use crate::storage::{
    available_storage_types, create_storage, StorageConfig, StorageError, TaskStorage, TimeRange,
};
use crate::{TaskStatus, WorkflowTask};

/// Migration configuration for backend-to-backend transfer
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigrationConfig {
    pub source_config: StorageConfig,
    pub target_config: StorageConfig,
    pub options: MigrationOptions,
}

/// Migration options and filters
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigrationOptions {
    /// Perform dry run without actual data transfer
    pub dry_run: bool,
    /// Filter tasks by status (None = migrate all)
    pub status_filter: Option<Vec<TaskStatus>>,
    /// Filter tasks created after this date
    pub created_after: Option<chrono::DateTime<chrono::Utc>>,
    /// Filter tasks created before this date
    pub created_before: Option<chrono::DateTime<chrono::Utc>>,
    /// Batch size for bulk operations
    pub batch_size: usize,
    /// Create backup before migration
    pub create_backup: bool,
    /// Backup path (auto-generated if None)
    pub backup_path: Option<String>,
    /// Verify data integrity after migration
    pub verify_integrity: bool,
    /// Maximum retry attempts for failed operations
    pub max_retries: u32,
    /// Continue migration on non-critical errors
    pub continue_on_error: bool,
}

impl Default for MigrationOptions {
    fn default() -> Self {
        Self {
            dry_run: false,
            status_filter: None,
            created_after: None,
            created_before: None,
            batch_size: 100,
            create_backup: true,
            backup_path: None,
            verify_integrity: true,
            max_retries: 3,
            continue_on_error: false,
        }
    }
}

/// Detailed migration report with statistics and errors
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigrationReport {
    pub migration_id: String,
    pub start_time: chrono::DateTime<chrono::Utc>,
    pub end_time: Option<chrono::DateTime<chrono::Utc>>,
    pub duration: Option<chrono::Duration>,
    pub source_backend: String,
    pub target_backend: String,
    pub status: MigrationStatus,
    pub statistics: MigrationStatistics,
    pub errors: Vec<MigrationError>,
    pub warnings: Vec<String>,
    pub phases: Vec<MigrationPhase>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum MigrationStatus {
    Pending,
    InProgress,
    Completed,
    Failed,
    Cancelled,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigrationStatistics {
    pub total_tasks_found: usize,
    pub tasks_migrated: usize,
    pub tasks_failed: usize,
    pub tasks_skipped: usize,
    pub audit_entries_migrated: usize,
    pub metrics_migrated: usize,
    pub data_size_bytes: u64,
    pub throughput_tasks_per_second: f64,
}

impl Default for MigrationStatistics {
    fn default() -> Self {
        Self {
            total_tasks_found: 0,
            tasks_migrated: 0,
            tasks_failed: 0,
            tasks_skipped: 0,
            audit_entries_migrated: 0,
            metrics_migrated: 0,
            data_size_bytes: 0,
            throughput_tasks_per_second: 0.0,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigrationPhase {
    pub phase: String,
    pub start_time: chrono::DateTime<chrono::Utc>,
    pub end_time: Option<chrono::DateTime<chrono::Utc>>,
    pub status: MigrationStatus,
    pub message: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigrationError {
    pub error_type: String,
    pub message: String,
    pub context: Option<String>,
    pub task_id: Option<String>,
    pub timestamp: chrono::DateTime<chrono::Utc>,
    pub retry_count: u32,
}

/// Progress callback for real-time migration updates
pub type ProgressCallback = Arc<dyn Fn(&MigrationProgress) + Send + Sync>;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MigrationProgress {
    pub phase: String,
    pub current_item: usize,
    pub total_items: usize,
    pub percentage: f64,
    pub message: String,
    pub throughput: f64,
}

/// Main storage migration orchestrator
pub struct StorageMigrator {
    config: MigrationConfig,
    report: MigrationReport,
    progress_callback: Option<ProgressCallback>,
}

impl StorageMigrator {
    /// Create a new migration instance
    pub fn new(config: MigrationConfig) -> Self {
        let report = MigrationReport {
            migration_id: Uuid::new_v4().to_string(),
            start_time: chrono::Utc::now(),
            end_time: None,
            duration: None,
            source_backend: config.source_config.storage_type.clone(),
            target_backend: config.target_config.storage_type.clone(),
            status: MigrationStatus::Pending,
            statistics: MigrationStatistics::default(),
            errors: Vec::new(),
            warnings: Vec::new(),
            phases: Vec::new(),
        };

        Self {
            config,
            report,
            progress_callback: None,
        }
    }

    /// Set progress callback for real-time updates
    pub fn with_progress_callback(mut self, callback: ProgressCallback) -> Self {
        self.progress_callback = Some(callback);
        self
    }

    /// Execute the complete migration process
    pub async fn execute(mut self) -> Result<MigrationReport> {
        info!(
            "Starting migration {} from {} to {}",
            self.report.migration_id, self.report.source_backend, self.report.target_backend
        );

        self.report.status = MigrationStatus::InProgress;
        let start = Instant::now();

        // Execute migration phases
        let result = self.run_migration_phases().await;

        // Update final statistics
        self.report.end_time = Some(chrono::Utc::now());
        self.report.duration = Some(chrono::Duration::from_std(start.elapsed())?);

        if let Some(duration) = self.report.duration {
            let seconds = duration.num_seconds() as f64;
            if seconds > 0.0 {
                self.report.statistics.throughput_tasks_per_second =
                    self.report.statistics.tasks_migrated as f64 / seconds;
            }
        }

        match result {
            Ok(_) => {
                self.report.status = MigrationStatus::Completed;
                info!(
                    "Migration {} completed successfully. Migrated {} tasks in {:?}",
                    self.report.migration_id,
                    self.report.statistics.tasks_migrated,
                    self.report.duration
                );
            }
            Err(e) => {
                self.report.status = MigrationStatus::Failed;
                self.add_error(
                    "migration_failed",
                    &format!("Migration failed: {}", e),
                    None,
                    None,
                );
                error!("Migration {} failed: {}", self.report.migration_id, e);

                // Initiate automatic rollback if configured
                if self.config.options.create_backup {
                    warn!("Migration failed - initiating automatic rollback");
                    match self.initiate_rollback().await {
                        Ok(rollback_report) => {
                            info!(
                                "Rollback {} completed with status: {:?}",
                                rollback_report.rollback_id, rollback_report.status
                            );
                            // Add rollback report to migration report warnings
                            self.report.warnings.push(format!(
                                "Automatic rollback executed: {}",
                                rollback_report.rollback_id
                            ));
                        }
                        Err(rollback_err) => {
                            error!("Rollback failed: {}", rollback_err);
                            self.add_error(
                                "rollback_failed",
                                &format!("Automatic rollback failed: {}", rollback_err),
                                None,
                                None,
                            );
                        }
                    }
                }
            }
        }

        Ok(self.report)
    }

    /// Run all migration phases in sequence
    async fn run_migration_phases(&mut self) -> Result<()> {
        // Phase 1: Validation
        self.add_phase("validation", "Validating migration configuration")
            .await?;
        self.validate_migration().await?;
        self.complete_phase("validation", "Configuration validated successfully")
            .await;

        // Phase 2: Storage Connection
        self.add_phase("connection", "Establishing storage connections")
            .await?;
        let (source_storage, target_storage) = self.connect_storages().await?;
        self.complete_phase("connection", "Storage connections established")
            .await;

        // Phase 3: Backup (if requested)
        if self.config.options.create_backup {
            self.add_phase("backup", "Creating backup").await?;
            self.create_backup(&source_storage).await?;
            self.complete_phase("backup", "Backup created successfully")
                .await;
        }

        // Phase 4: Data Discovery
        self.add_phase("discovery", "Discovering data to migrate")
            .await?;
        let tasks_to_migrate = self.discover_tasks(&source_storage).await?;
        self.report.statistics.total_tasks_found = tasks_to_migrate.len();
        self.complete_phase(
            "discovery",
            &format!("Found {} tasks to migrate", tasks_to_migrate.len()),
        )
        .await;

        // Phase 5: Data Migration
        if !tasks_to_migrate.is_empty() {
            self.add_phase("migration", "Migrating tasks").await?;
            self.migrate_tasks(&source_storage, &target_storage, tasks_to_migrate)
                .await?;
            self.complete_phase(
                "migration",
                &format!("Migrated {} tasks", self.report.statistics.tasks_migrated),
            )
            .await;
        }

        // Phase 6: Audit and Metrics Migration
        self.add_phase("metadata", "Migrating audit logs and metrics")
            .await?;
        self.migrate_metadata(&source_storage, &target_storage)
            .await?;
        self.complete_phase("metadata", "Metadata migration completed")
            .await;

        // Phase 7: Verification (if requested)
        if self.config.options.verify_integrity {
            self.add_phase("verification", "Verifying data integrity")
                .await?;
            self.verify_migration_integrity(&source_storage, &target_storage)
                .await?;
            self.complete_phase("verification", "Data integrity verified")
                .await;
        }

        Ok(())
    }

    /// Validate migration configuration and backends
    async fn validate_migration(&mut self) -> Result<()> {
        // Validate source configuration
        self.config
            .source_config
            .validate()
            .context("Source storage configuration validation failed")?;

        // Validate target configuration
        self.config
            .target_config
            .validate()
            .context("Target storage configuration validation failed")?;

        // Check if backends are different
        if self.config.source_config.storage_type == self.config.target_config.storage_type
            && self.config.source_config.data_dir == self.config.target_config.data_dir
        {
            return Err(anyhow!("Source and target configurations are identical"));
        }

        // Validate available storage types
        let available_types = available_storage_types();
        if !available_types.contains(&self.config.source_config.storage_type) {
            return Err(anyhow!(
                "Source storage type '{}' not available. Available types: {}",
                self.config.source_config.storage_type,
                available_types.join(", ")
            ));
        }
        if !available_types.contains(&self.config.target_config.storage_type) {
            return Err(anyhow!(
                "Target storage type '{}' not available. Available types: {}",
                self.config.target_config.storage_type,
                available_types.join(", ")
            ));
        }

        info!("Migration configuration validation passed");
        Ok(())
    }

    /// Establish connections to both storage backends
    async fn connect_storages(
        &mut self,
    ) -> Result<(
        std::sync::Arc<dyn TaskStorage>,
        std::sync::Arc<dyn TaskStorage>,
    )> {
        // Connect to source storage
        let source_storage = create_storage(self.config.source_config.clone())
            .await
            .context("Failed to connect to source storage")?;

        // Verify source storage health
        match source_storage.health_check().await {
            Ok(true) => info!("Source storage health check passed"),
            Ok(false) => return Err(anyhow!("Source storage health check failed")),
            Err(e) => return Err(anyhow!("Source storage health check error: {}", e)),
        }

        // Connect to target storage
        let target_storage = create_storage(self.config.target_config.clone())
            .await
            .context("Failed to connect to target storage")?;

        // Verify target storage health
        match target_storage.health_check().await {
            Ok(true) => info!("Target storage health check passed"),
            Ok(false) => return Err(anyhow!("Target storage health check failed")),
            Err(e) => return Err(anyhow!("Target storage health check error: {}", e)),
        }

        Ok((source_storage, target_storage))
    }

    /// Create backup of source storage
    async fn create_backup(
        &mut self,
        source_storage: &std::sync::Arc<dyn TaskStorage>,
    ) -> Result<()> {
        if self.config.options.dry_run {
            info!("DRY RUN: Would create backup");
            return Ok(());
        }

        let backup_path = match &self.config.options.backup_path {
            Some(path) => path.clone(),
            None => {
                format!(
                    "./backup_{}_{}.json",
                    self.config.source_config.storage_type,
                    chrono::Utc::now().format("%Y%m%d_%H%M%S")
                )
            }
        };

        match source_storage.create_backup(&backup_path).await {
            Ok(_) => {
                info!("Backup created at: {}", backup_path);
                Ok(())
            }
            Err(StorageError::BackendError(_)) => {
                warn!("Backup functionality not supported by source backend, skipping");
                Ok(())
            }
            Err(e) => Err(anyhow!("Failed to create backup: {}", e)),
        }
    }

    /// Discover tasks that match migration criteria
    async fn discover_tasks(
        &mut self,
        source_storage: &std::sync::Arc<dyn TaskStorage>,
    ) -> Result<Vec<WorkflowTask>> {
        let mut tasks = source_storage
            .search_tasks(
                None, // name_pattern
                self.config.options.status_filter.clone(),
                self.config.options.created_after,
                self.config.options.created_before,
                None, // limit
                None, // offset
            )
            .await?;

        // Sort by creation time for consistent ordering
        tasks.sort_by(|a, b| a.created_at.cmp(&b.created_at));

        debug!("Discovered {} tasks for migration", tasks.len());
        Ok(tasks)
    }

    /// Migrate tasks in batches
    async fn migrate_tasks(
        &mut self,
        _source_storage: &std::sync::Arc<dyn TaskStorage>,
        target_storage: &std::sync::Arc<dyn TaskStorage>,
        tasks: Vec<WorkflowTask>,
    ) -> Result<()> {
        let total_tasks = tasks.len();
        let batch_size = self.config.options.batch_size;

        for (batch_index, batch) in tasks.chunks(batch_size).enumerate() {
            let current_batch_start = batch_index * batch_size;

            self.update_progress(
                "migration",
                current_batch_start,
                total_tasks,
                &format!(
                    "Migrating batch {} of {}",
                    batch_index + 1,
                    total_tasks.div_ceil(batch_size)
                ),
            );

            if self.config.options.dry_run {
                info!("DRY RUN: Would migrate batch of {} tasks", batch.len());
                self.report.statistics.tasks_migrated += batch.len();
                continue;
            }

            let batch_tasks: Vec<(WorkflowTask, u8)> = batch
                .iter()
                .map(|task| (task.clone(), 1)) // Default priority
                .collect();

            self.migrate_batch_with_retry(target_storage, batch_tasks, batch.len())
                .await?;
        }

        Ok(())
    }

    /// Migrate batch with retry logic
    async fn migrate_batch_with_retry(
        &mut self,
        target_storage: &std::sync::Arc<dyn TaskStorage>,
        batch_tasks: Vec<(WorkflowTask, u8)>,
        batch_size: usize,
    ) -> Result<()> {
        let mut retry_count = 0;
        loop {
            match target_storage.enqueue_batch(batch_tasks.clone()).await {
                Ok(_) => {
                    self.report.statistics.tasks_migrated += batch_size;
                    debug!("Successfully migrated batch of {} tasks", batch_size);
                    return Ok(());
                }
                Err(e) => {
                    retry_count += 1;
                    if retry_count <= self.config.options.max_retries {
                        warn!(
                            "Batch migration failed (attempt {}/{}): {}. Retrying...",
                            retry_count, self.config.options.max_retries, e
                        );
                        tokio::time::sleep(tokio::time::Duration::from_secs(retry_count as u64))
                            .await;
                        continue;
                    }

                    self.add_error(
                        "batch_migration_failed",
                        &format!(
                            "Failed to migrate batch after {} retries: {}",
                            self.config.options.max_retries, e
                        ),
                        Some(format!("Batch {} tasks", batch_size)),
                        None,
                    );

                    if !self.config.options.continue_on_error {
                        return Err(anyhow!("Batch migration failed: {}", e));
                    }

                    self.report.statistics.tasks_failed += batch_size;
                    return Ok(());
                }
            }
        }
    }

    /// Migrate audit logs and metrics
    async fn migrate_metadata(
        &mut self,
        _source_storage: &std::sync::Arc<dyn TaskStorage>,
        target_storage: &std::sync::Arc<dyn TaskStorage>,
    ) -> Result<()> {
        if self.config.options.dry_run {
            info!("DRY RUN: Would migrate metadata");
            return Ok(());
        }

        // Migrate audit logs
        let time_range = TimeRange {
            start: self
                .config
                .options
                .created_after
                .unwrap_or_else(|| chrono::Utc::now() - chrono::Duration::days(365)),
            end: self
                .config
                .options
                .created_before
                .unwrap_or_else(chrono::Utc::now),
        };

        match _source_storage.get_audit_log(time_range.clone()).await {
            Ok(audit_entries) => {
                for entry in audit_entries {
                    if let Err(e) = target_storage.record_audit_entry(entry).await {
                        warn!("Failed to migrate audit entry: {}", e);
                    } else {
                        self.report.statistics.audit_entries_migrated += 1;
                    }
                }
            }
            Err(e) => {
                warn!("Failed to retrieve audit logs: {}", e);
            }
        }

        // Migrate metrics
        match _source_storage.get_metrics(time_range).await {
            Ok(metrics) => {
                for metric in metrics {
                    if let Err(e) = target_storage.record_metric(metric).await {
                        warn!("Failed to migrate metric: {}", e);
                    } else {
                        self.report.statistics.metrics_migrated += 1;
                    }
                }
            }
            Err(e) => {
                warn!("Failed to retrieve metrics: {}", e);
            }
        }

        Ok(())
    }

    /// Verify migration integrity by comparing data
    async fn verify_migration_integrity(
        &mut self,
        source_storage: &std::sync::Arc<dyn TaskStorage>,
        target_storage: &std::sync::Arc<dyn TaskStorage>,
    ) -> Result<()> {
        // Get all tasks from both storages
        let source_tasks = source_storage.list_tasks(None).await?;
        let target_tasks = target_storage.list_tasks(None).await?;

        // Create task maps for comparison
        let target_map: HashMap<String, &WorkflowTask> = target_tasks
            .iter()
            .map(|task| (task.id.clone(), task))
            .collect();

        // Verify all migrated tasks exist in target
        let mut integrity_errors = 0;
        for source_task in &source_tasks {
            match target_map.get(&source_task.id) {
                Some(target_task) => {
                    // Compare task data
                    if source_task.name != target_task.name
                        || source_task.command != target_task.command
                        || source_task.status != target_task.status
                    {
                        self.add_error(
                            "data_integrity_error",
                            "Task data mismatch between source and target",
                            None,
                            Some(source_task.id.clone()),
                        );
                        integrity_errors += 1;
                    }
                }
                None => {
                    self.add_error(
                        "missing_task_error",
                        "Task found in source but missing in target",
                        None,
                        Some(source_task.id.clone()),
                    );
                    integrity_errors += 1;
                }
            }
        }

        if integrity_errors > 0 {
            return Err(anyhow!(
                "Data integrity verification failed with {} errors",
                integrity_errors
            ));
        }

        info!(
            "Data integrity verification passed for {} tasks",
            source_tasks.len()
        );
        Ok(())
    }

    /// Add a new migration phase
    async fn add_phase(&mut self, phase: &str, message: &str) -> Result<()> {
        let phase_info = MigrationPhase {
            phase: phase.to_string(),
            start_time: chrono::Utc::now(),
            end_time: None,
            status: MigrationStatus::InProgress,
            message: message.to_string(),
        };

        self.report.phases.push(phase_info);
        self.update_progress(phase, 0, 100, message);
        info!("Starting phase: {}", message);
        Ok(())
    }

    /// Complete a migration phase
    async fn complete_phase(&mut self, phase: &str, message: &str) {
        if let Some(phase_info) = self
            .report
            .phases
            .iter_mut()
            .find(|p| p.phase == phase && p.end_time.is_none())
        {
            phase_info.end_time = Some(chrono::Utc::now());
            phase_info.status = MigrationStatus::Completed;
            phase_info.message = message.to_string();
        }

        self.update_progress(phase, 100, 100, message);
        info!("Completed phase: {}", message);
    }

    /// Add an error to the migration report
    fn add_error(
        &mut self,
        error_type: &str,
        message: &str,
        context: Option<String>,
        task_id: Option<String>,
    ) {
        let error = MigrationError {
            error_type: error_type.to_string(),
            message: message.to_string(),
            context,
            task_id,
            timestamp: chrono::Utc::now(),
            retry_count: 0,
        };

        self.report.errors.push(error);
    }

    /// Update migration progress and call progress callback
    fn update_progress(&self, phase: &str, current: usize, total: usize, message: &str) {
        if let Some(callback) = &self.progress_callback {
            let percentage = if total > 0 {
                (current as f64 / total as f64) * 100.0
            } else {
                0.0
            };

            let progress = MigrationProgress {
                phase: phase.to_string(),
                current_item: current,
                total_items: total,
                percentage,
                message: message.to_string(),
                throughput: self.report.statistics.throughput_tasks_per_second,
            };

            callback(&progress);
        }
    }

    /// Initiate rollback after migration failure
    async fn initiate_rollback(&self) -> Result<RollbackReport> {
        let backup_path = match &self.config.options.backup_path {
            Some(path) => path.clone(),
            None => {
                format!(
                    "./backup_{}_{}.json",
                    self.config.source_config.storage_type,
                    self.report.start_time.format("%Y%m%d_%H%M%S")
                )
            }
        };

        let rollback_strategy = if std::path::Path::new(&backup_path).exists() {
            RollbackStrategy::RestoreFromBackup
        } else {
            RollbackStrategy::Manual
        };

        let rollback_config = RollbackConfig {
            backup_path: backup_path.clone(),
            migration_id: self.report.migration_id.clone(),
            rollback_strategy,
        };

        let rollback_manager = RollbackManager::new(rollback_config);

        // Create target storage for rollback
        let target_storage = create_storage(self.config.target_config.clone())
            .await
            .context("Failed to recreate target storage for rollback")?;

        rollback_manager.execute_rollback(&target_storage).await
    }
}

/// Rollback configuration for failed migrations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RollbackConfig {
    pub backup_path: String,
    pub migration_id: String,
    pub rollback_strategy: RollbackStrategy,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RollbackStrategy {
    /// Restore from backup file
    RestoreFromBackup,
    /// Clear target storage and restore source
    ClearTargetRestoreSource,
    /// Manual rollback with detailed instructions
    Manual,
}

/// Rollback manager for handling failed migrations
pub struct RollbackManager {
    config: RollbackConfig,
    report: RollbackReport,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RollbackReport {
    pub rollback_id: String,
    pub migration_id: String,
    pub start_time: chrono::DateTime<chrono::Utc>,
    pub end_time: Option<chrono::DateTime<chrono::Utc>>,
    pub status: RollbackStatus,
    pub strategy_used: RollbackStrategy,
    pub actions_performed: Vec<RollbackAction>,
    pub errors: Vec<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum RollbackStatus {
    Pending,
    InProgress,
    Completed,
    Failed,
    PartiallyCompleted,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RollbackAction {
    pub action: String,
    pub timestamp: chrono::DateTime<chrono::Utc>,
    pub success: bool,
    pub details: String,
}

impl RollbackManager {
    /// Create a new rollback manager
    pub fn new(config: RollbackConfig) -> Self {
        let report = RollbackReport {
            rollback_id: Uuid::new_v4().to_string(),
            migration_id: config.migration_id.clone(),
            start_time: chrono::Utc::now(),
            end_time: None,
            status: RollbackStatus::Pending,
            strategy_used: config.rollback_strategy.clone(),
            actions_performed: Vec::new(),
            errors: Vec::new(),
        };

        Self { config, report }
    }

    /// Execute rollback based on the configured strategy
    pub async fn execute_rollback(
        mut self,
        target_storage: &std::sync::Arc<dyn TaskStorage>,
    ) -> Result<RollbackReport> {
        info!(
            "Starting rollback {} for migration {}",
            self.report.rollback_id, self.report.migration_id
        );

        self.report.status = RollbackStatus::InProgress;

        let result = match self.config.rollback_strategy {
            RollbackStrategy::RestoreFromBackup => self.restore_from_backup(target_storage).await,
            RollbackStrategy::ClearTargetRestoreSource => {
                self.clear_target_storage(target_storage).await
            }
            RollbackStrategy::Manual => self.generate_manual_instructions().await,
        };

        self.report.end_time = Some(chrono::Utc::now());

        match result {
            Ok(_) => {
                self.report.status = if self.report.errors.is_empty() {
                    RollbackStatus::Completed
                } else {
                    RollbackStatus::PartiallyCompleted
                };
                info!(
                    "Rollback {} completed with status: {:?}",
                    self.report.rollback_id, self.report.status
                );
            }
            Err(e) => {
                self.report.status = RollbackStatus::Failed;
                self.report.errors.push(format!("Rollback failed: {}", e));
                error!("Rollback {} failed: {}", self.report.rollback_id, e);
            }
        }

        Ok(self.report)
    }

    /// Restore target storage from backup
    async fn restore_from_backup(
        &mut self,
        target_storage: &std::sync::Arc<dyn TaskStorage>,
    ) -> Result<()> {
        self.add_action("backup_restore_start", true, "Starting backup restoration");

        match target_storage
            .restore_from_backup(&self.config.backup_path)
            .await
        {
            Ok(_) => {
                self.add_action(
                    "backup_restore_success",
                    true,
                    &format!(
                        "Successfully restored from backup: {}",
                        self.config.backup_path
                    ),
                );
                Ok(())
            }
            Err(StorageError::BackendError(_)) => {
                let error_msg = "Backup restoration not supported by target backend";
                self.add_action("backup_restore_unsupported", false, error_msg);
                self.report.errors.push(error_msg.to_string());

                // Fall back to manual clear
                warn!("Falling back to manual clear strategy");
                self.clear_target_storage(target_storage).await
            }
            Err(e) => {
                let error_msg = format!("Failed to restore from backup: {}", e);
                self.add_action("backup_restore_failed", false, &error_msg);
                self.report.errors.push(error_msg.clone());
                Err(anyhow!(error_msg))
            }
        }
    }

    /// Clear target storage (remove migrated data)
    async fn clear_target_storage(
        &mut self,
        target_storage: &std::sync::Arc<dyn TaskStorage>,
    ) -> Result<()> {
        self.add_action(
            "clear_target_start",
            true,
            "Starting target storage cleanup",
        );

        // Get all tasks from target storage
        match target_storage.list_tasks(None).await {
            Ok(tasks) => {
                let task_count = tasks.len();
                self.add_action(
                    "clear_target_discovered",
                    true,
                    &format!("Found {} tasks to remove from target", task_count),
                );

                let failed_count = 0;

                // Note: TaskStorage trait doesn't have delete_task method
                // This is a limitation - in a real implementation, we'd need:
                // 1. Add delete_task method to TaskStorage trait
                // 2. Or use storage-specific cleanup methods
                // 3. Or mark tasks as "rolled back" status

                // For now, we'll document what should be done
                self.add_action(
                    "clear_target_limitation",
                    false,
                    "TaskStorage trait lacks delete_task method - manual cleanup required",
                );

                self.report.errors.push(
                    "Automatic task removal not supported by current TaskStorage interface. \
                     Manual cleanup of target storage required."
                        .to_string(),
                );

                // If we had delete functionality, it would look like:
                // for task in tasks {
                //     match target_storage.delete_task(&task.id).await {
                //         Ok(_) => removed_count += 1,
                //         Err(e) => {
                //             failed_count += 1;
                //             self.report.errors.push(format!("Failed to delete task {}: {}",
                // task.id, e));         }
                //     }
                // }

                self.add_action(
                    "clear_target_incomplete",
                    false,
                    &format!("Target cleanup incomplete - {} tasks remain", task_count),
                );

                if failed_count == 0 {
                    Ok(())
                } else {
                    Err(anyhow!(
                        "Failed to remove {} tasks from target storage",
                        failed_count
                    ))
                }
            }
            Err(e) => {
                let error_msg = format!("Failed to list tasks for cleanup: {}", e);
                self.add_action("clear_target_failed", false, &error_msg);
                self.report.errors.push(error_msg.clone());
                Err(anyhow!(error_msg))
            }
        }
    }

    /// Generate manual rollback instructions
    async fn generate_manual_instructions(&mut self) -> Result<()> {
        self.add_action(
            "manual_instructions_start",
            true,
            "Generating manual rollback instructions",
        );

        let instructions = format!(
            "Manual Rollback Instructions for Migration \
             {}\n=============================================\n\nMigration ID: {}\nRollback ID: \
             {}\nTimestamp: {}\n\nSteps to rollback:\n1. Stop the orchestrator service\n2. If \
             backup exists at '{}', restore it to target storage\n3. Verify target storage \
             contains original data\n4. Remove any partially migrated data\n5. Restart \
             orchestrator service\n\nStorage-specific cleanup commands:\n- For filesystem: Remove \
             or rename target directory\n- For SurrealDB embedded: Delete database files in \
             target directory\n- For SurrealDB server: Connect and drop/recreate \
             database\n\nIMPORTANT: Test data integrity before resuming operations!",
            self.report.migration_id,
            self.report.migration_id,
            self.report.rollback_id,
            chrono::Utc::now().format("%Y-%m-%d %H:%M:%S UTC"),
            self.config.backup_path
        );

        // Save instructions to file
        let instructions_file = format!("rollback_instructions_{}.txt", self.report.rollback_id);
        match std::fs::write(&instructions_file, &instructions) {
            Ok(_) => {
                self.add_action(
                    "manual_instructions_saved",
                    true,
                    &format!("Manual instructions saved to: {}", instructions_file),
                );
                info!(
                    "Manual rollback instructions saved to: {}",
                    instructions_file
                );
            }
            Err(e) => {
                self.add_action(
                    "manual_instructions_save_failed",
                    false,
                    &format!("Failed to save instructions: {}", e),
                );
                // Still provide instructions via logging
                info!("Manual rollback instructions:\n{}", instructions);
            }
        }

        Ok(())
    }

    /// Add a rollback action to the report
    fn add_action(&mut self, action: &str, success: bool, details: &str) {
        let action_record = RollbackAction {
            action: action.to_string(),
            timestamp: chrono::Utc::now(),
            success,
            details: details.to_string(),
        };

        self.report.actions_performed.push(action_record);

        if success {
            debug!("Rollback action completed: {} - {}", action, details);
        } else {
            warn!("Rollback action failed: {} - {}", action, details);
        }
    }
}

/// Utility functions for common migration scenarios
impl StorageMigrator {
    /// Create a simple filesystem to SurrealDB embedded migration
    pub fn filesystem_to_embedded(
        source_dir: &str,
        target_dir: &str,
        options: Option<MigrationOptions>,
    ) -> Self {
        let config = MigrationConfig {
            source_config: StorageConfig {
                storage_type: "filesystem".to_string(),
                data_dir: source_dir.to_string(),
                ..Default::default()
            },
            target_config: StorageConfig {
                storage_type: "surrealdb-embedded".to_string(),
                data_dir: target_dir.to_string(),
                ..Default::default()
            },
            options: options.unwrap_or_default(),
        };

        Self::new(config)
    }

    /// Create a SurrealDB embedded to server migration
    pub fn embedded_to_server(
        source_dir: &str,
        server_url: &str,
        username: &str,
        password: &str,
        options: Option<MigrationOptions>,
    ) -> Self {
        let config = MigrationConfig {
            source_config: StorageConfig {
                storage_type: "surrealdb-embedded".to_string(),
                data_dir: source_dir.to_string(),
                ..Default::default()
            },
            target_config: StorageConfig {
                storage_type: "surrealdb-server".to_string(),
                data_dir: "".to_string(),
                surrealdb_url: Some(server_url.to_string()),
                surrealdb_username: Some(username.to_string()),
                surrealdb_password: Some(password.to_string()),
                ..Default::default()
            },
            options: options.unwrap_or_default(),
        };

        Self::new(config)
    }
}

#[cfg(test)]
mod tests;
