"""Snapshot mixin: VM snapshots, restore, and deletion."""

from __future__ import annotations

import time
from pathlib import Path

import structlog

from proxym.virt._config import VMConfig
from proxym.virt._enums import VMBackend, VMState

logger = structlog.get_logger()


class _SnapshotMixin:
    """VM snapshots: create, restore, delete VM."""

    def snapshot_vm(self, vm_id: str, name: str = "") -> bool:
        """Create a snapshot for quick restore."""
        vm = self.vms.get(vm_id)
        if not vm:
            return False
        snap_name = name or f"snap-{int(time.time())}"

        if vm.backend == VMBackend.CLONEBOX.value:
            return self._snapshot_clonebox(vm, snap_name)

        result = self._run(
            f"virsh snapshot-create-as {vm.id} {snap_name} --atomic",
            check=False,
        )
        if result.returncode == 0:
            vm.snapshot_name = snap_name
            self._save_config(vm)
            return True
        return False

    def _snapshot_clonebox(self, vm: VMConfig, snap_name: str) -> bool:
        """Snapshot via clonebox backend."""
        cb = self._get_clonebox()
        if not cb:
            return False
        result = cb.snapshot(vm.id, snap_name)
        if result.success:
            vm.snapshot_name = snap_name
            self._save_config(vm)
            return True
        return False

    def restore_snapshot(self, vm_id: str, snapshot_name: str = "") -> bool:
        """Restore a previously saved snapshot."""
        vm = self.vms.get(vm_id)
        if not vm:
            return False
        snap = snapshot_name or vm.snapshot_name
        if not snap:
            return False

        if vm.backend == VMBackend.CLONEBOX.value:
            cb = self._get_clonebox()
            if cb:
                return cb.restore_snapshot(vm.id, snap).success

        result = self._run(f"virsh snapshot-revert {vm.id} {snap}", check=False)
        return result.returncode == 0

    def delete_vm(self, vm_id: str) -> bool:
        """Delete a VM and all its resources."""
        vm = self.vms.get(vm_id)
        if not vm:
            return False

        if vm.backend == VMBackend.CLONEBOX.value:
            cb = self._get_clonebox()
            if cb:
                cb.delete_vm(vm.id)
        else:
            self.stop_vm(vm_id, force=True)
            self._run(f"virsh undefine {vm.id} --snapshots-metadata", check=False)
            overlay = Path(vm.overlay_path)
            if overlay.exists():
                overlay.unlink()

        cfg = self.config_dir / f"{vm.id}.json"
        if cfg.exists():
            cfg.unlink()
        del self.vms[vm_id]
        logger.info("vm_deleted", id=vm_id)
        return True
