"""Simple rollback manager implementation."""

import shutil
from pathlib import Path
from typing import Dict, Any, Optional
from datetime import datetime
from .snapshot import Snapshot


class SimpleRollbackManager:
    """Simple in-memory rollback manager with file.move support."""

    def __init__(self):
        """Initialize rollback manager."""
        self._snapshots: Dict[str, Snapshot] = {}
        self._snapshot_counter = 0

    def create_snapshot(self, action_id: str, parameters: Dict[str, Any]) -> Snapshot:
        """Create snapshot before execution.
        
        Args:
            action_id: Action identifier
            parameters: Action parameters
            
        Returns:
            Snapshot object
        """
        self._snapshot_counter += 1
        snapshot_id = f"snap_{self._snapshot_counter}_{datetime.now().timestamp()}"
        
        # Capture state based on action type
        state = {}
        
        if action_id == "file.move":
            source = parameters.get("source")
            if source and Path(source).exists():
                state = {
                    "source_exists": True,
                    "source_path": source,
                    "destination_path": parameters.get("destination"),
                    "source_is_file": Path(source).is_file()
                }
            else:
                state = {"source_exists": False}
        
        snapshot = Snapshot(
            snapshot_id=snapshot_id,
            action_id=action_id,
            parameters=parameters,
            state=state,
            timestamp=datetime.now(),
            committed=False
        )
        
        self._snapshots[snapshot_id] = snapshot
        return snapshot

    def rollback(self, snapshot_id: str) -> Dict[str, Any]:
        """Rollback to snapshot.
        
        Args:
            snapshot_id: Snapshot identifier
            
        Returns:
            Rollback result
        """
        snapshot = self._snapshots.get(snapshot_id)
        
        if not snapshot:
            return {
                "success": False,
                "message": f"Snapshot not found: {snapshot_id}"
            }
        
        if snapshot.committed:
            return {
                "success": False,
                "message": "Snapshot already committed, cannot rollback"
            }
        
        # Perform rollback based on action type
        if snapshot.action_id == "file.move":
            return self._rollback_file_move(snapshot)
        else:
            return {
                "success": False,
                "message": f"Rollback not supported for action: {snapshot.action_id}"
            }

    def _rollback_file_move(self, snapshot: Snapshot) -> Dict[str, Any]:
        """Rollback file.move operation.
        
        Args:
            snapshot: Snapshot to rollback
            
        Returns:
            Rollback result
        """
        state = snapshot.state
        
        if not state.get("source_exists"):
            return {
                "success": False,
                "message": "Source did not exist before operation, nothing to rollback"
            }
        
        source_path = state.get("source_path")
        dest_path = state.get("destination_path")
        
        # Check if file was moved (destination exists, source doesn't)
        if Path(dest_path).exists() and not Path(source_path).exists():
            try:
                # Move file back to original location
                shutil.move(dest_path, source_path)
                return {
                    "success": True,
                    "message": f"Rolled back: moved {dest_path} back to {source_path}",
                    "snapshot_id": snapshot.snapshot_id
                }
            except Exception as e:
                return {
                    "success": False,
                    "message": f"Rollback failed: {str(e)}"
                }
        else:
            return {
                "success": False,
                "message": "File state unchanged, no rollback needed"
            }

    def commit(self, snapshot_id: str) -> Dict[str, Any]:
        """Commit snapshot (mark as successful, prevent rollback).
        
        Args:
            snapshot_id: Snapshot identifier
            
        Returns:
            Commit result
        """
        snapshot = self._snapshots.get(snapshot_id)
        
        if not snapshot:
            return {
                "success": False,
                "message": f"Snapshot not found: {snapshot_id}"
            }
        
        snapshot.committed = True
        return {
            "success": True,
            "message": f"Snapshot committed: {snapshot_id}",
            "snapshot_id": snapshot_id
        }

    def get_snapshot(self, snapshot_id: str) -> Optional[Snapshot]:
        """Get snapshot by ID.
        
        Args:
            snapshot_id: Snapshot identifier
            
        Returns:
            Snapshot or None
        """
        return self._snapshots.get(snapshot_id)

    def list_snapshots(self) -> list[Snapshot]:
        """List all snapshots.
        
        Returns:
            List of snapshots
        """
        return list(self._snapshots.values())

    def cleanup_committed(self) -> int:
        """Remove committed snapshots from memory.
        
        Returns:
            Number of snapshots removed
        """
        to_remove = [sid for sid, snap in self._snapshots.items() if snap.committed]
        for sid in to_remove:
            del self._snapshots[sid]
        return len(to_remove)
