"""QEMU worker transition semantics."""

import uuid
from datetime import UTC, datetime
from typing import cast

from app.simulation.clock import Clock
from app.tasks.qemu import qemu_handler
from app.tasks.repository import Task, TaskRepository


class ImmediateClock:
    async def now(self) -> datetime:
        return datetime(2026, 1, 1, tzinfo=UTC)

    async def sleep(self, seconds: float) -> None:
        assert seconds == 1.0


class Connection:
    def __init__(self) -> None:
        self.states: list[str] = []

    async def fetchrow(self, sql: str, resource_id: uuid.UUID) -> dict[str, object]:
        del sql, resource_id
        return {"state": '{"status":"stopped"}'}

    async def execute(self, sql: str, resource_id: uuid.UUID, state: str) -> str:
        del sql, resource_id
        self.states.append(state)
        return "UPDATE 1"


class Acquire:
    def __init__(self, connection: Connection) -> None:
        self.connection = connection

    async def __aenter__(self) -> Connection:
        return self.connection

    async def __aexit__(self, *args: object) -> None:
        return None


class Pool:
    def __init__(self, connection: Connection) -> None:
        self.connection = connection

    def acquire(self) -> Acquire:
        return Acquire(self.connection)


class Repository:
    def __init__(self) -> None:
        self.connection = Connection()
        self.pool = Pool(self.connection)
        self.logs: list[str] = []

    async def append_log(self, task_id: uuid.UUID, message: str) -> None:
        del task_id
        self.logs.append(message)


class Transaction:
    async def __aenter__(self) -> None:
        return None

    async def __aexit__(self, *args: object) -> None:
        return None


class CrudConnection:
    def __init__(self) -> None:
        self.commands: list[str] = []

    def transaction(self) -> Transaction:
        return Transaction()

    async def fetchrow(self, sql: str, *args: object) -> dict[str, object] | None:
        del args
        if "FROM nodes" in sql:
            return {"id": uuid.uuid4(), "cluster_id": uuid.uuid4()}
        if "JOIN virtual_machines" in sql:
            return {"state": '{"status":"stopped","name":"old"}', "config": '{"name":"old"}'}
        if "SELECT state FROM resources" in sql:
            return {"state": '{"status":"stopped","name":"old"}'}
        if "SELECT config FROM virtual_machines" in sql:
            return {"config": '{"scsi0":"local-lvm:vm-150-disk-0,size=10G"}'}
        if "FROM snapshots" in sql:
            return {
                "state": (
                    '{"resource_state":{"status":"stopped","name":"old"},"config":{"name":"old"}}'
                )
            }
        return None

    async def execute(self, sql: str, *args: object) -> str:
        del args
        self.commands.append(sql)
        return "DELETE 1" if sql.startswith("DELETE") else "UPDATE 1"


class CrudRepository:
    def __init__(self) -> None:
        self.connection = CrudConnection()
        self.pool = Pool(cast(Connection, self.connection))
        self.logs: list[str] = []

    async def append_log(self, _task_id: uuid.UUID, message: str) -> None:
        self.logs.append(message)


async def test_qemu_worker_applies_intermediate_and_final_states() -> None:
    repository = Repository()
    task = Task(
        uuid.uuid4(),
        "UPID:test",
        "qemu-start",
        "running",
        {"resource_id": str(uuid.uuid4())},
        0,
        False,
        1,
    )

    result = await qemu_handler(cast(TaskRepository, repository), cast(Clock, ImmediateClock()))(
        task
    )

    assert result == {"status": "running"}
    assert '"starting"' in repository.connection.states[0]
    assert '"running"' in repository.connection.states[1]
    assert repository.logs == ["VM start started", "VM start completed"]


async def test_qemu_worker_create_update_and_delete_are_persistent() -> None:
    repository = CrudRepository()
    handler = qemu_handler(cast(TaskRepository, repository), cast(Clock, ImmediateClock()))
    resource_id = uuid.uuid4()

    created = await handler(
        Task(
            uuid.uuid4(),
            "UPID:create",
            "qemu-create",
            "running",
            {"node": "pve1", "vmid": 150, "config": {"name": "new"}},
            0,
            False,
            1,
        )
    )
    updated = await handler(
        Task(
            uuid.uuid4(),
            "UPID:update",
            "qemu-update",
            "running",
            {
                "resource_id": str(resource_id),
                "changes": {"name": "changed", "cores": 4},
                "delete": "unused",
            },
            0,
            False,
            1,
        )
    )
    deleted = await handler(
        Task(
            uuid.uuid4(),
            "UPID:delete",
            "qemu-delete",
            "running",
            {"resource_id": str(resource_id)},
            0,
            False,
            1,
        )
    )

    assert created == {"vmid": 150, "status": "stopped"}
    assert updated == {"updated": ["cores", "name"], "deleted": ["unused"]}
    assert deleted == {"deleted": True}
    assert any("INSERT INTO resources" in command for command in repository.connection.commands)
    assert any("UPDATE virtual_machines" in command for command in repository.connection.commands)
    assert any("DELETE FROM resources" in command for command in repository.connection.commands)


async def test_qemu_worker_snapshot_create_rollback_and_delete_are_persistent() -> None:
    repository = CrudRepository()
    handler = qemu_handler(cast(TaskRepository, repository), cast(Clock, ImmediateClock()))
    resource_id = uuid.uuid4()

    async def run(operation: str, **payload: object) -> dict[str, object]:
        result = await handler(
            Task(
                uuid.uuid4(),
                f"UPID:{operation}",
                f"qemu-snapshot-{operation}",
                "running",
                {"resource_id": str(resource_id), "snapname": "baseline", **payload},
                0,
                False,
                1,
            )
        )
        assert result is not None
        return cast(dict[str, object], result)

    assert await run("create", description="stable") == {
        "snapshot": "baseline",
        "operation": "create",
    }
    assert await run("rollback", start=True) == {
        "snapshot": "baseline",
        "operation": "rollback",
    }
    assert await run("delete") == {"snapshot": "baseline", "operation": "delete"}
    commands = repository.connection.commands
    assert any("INSERT INTO snapshots" in command for command in commands)
    assert any("UPDATE virtual_machines" in command for command in commands)
    assert any("DELETE FROM snapshots" in command for command in commands)


async def test_qemu_worker_clone_and_migrate_are_persistent() -> None:
    repository = CrudRepository()
    handler = qemu_handler(cast(TaskRepository, repository), cast(Clock, ImmediateClock()))
    resource_id = uuid.uuid4()

    cloned = await handler(
        Task(
            uuid.uuid4(),
            "UPID:clone",
            "qemu-clone",
            "running",
            {
                "source_resource_id": str(resource_id),
                "node": "pve1",
                "vmid": 151,
                "name": "clone",
            },
            0,
            False,
            1,
        )
    )
    migrated = await handler(
        Task(
            uuid.uuid4(),
            "UPID:migrate",
            "qemu-migrate",
            "running",
            {"resource_id": str(resource_id), "target": "pve2"},
            0,
            False,
            1,
        )
    )
    moved = await handler(
        Task(
            uuid.uuid4(),
            "UPID:move",
            "qemu-move-disk",
            "running",
            {
                "resource_id": str(resource_id),
                "disk": "scsi0",
                "target_disk": "scsi0",
                "storage": "local",
                "delete": True,
            },
            0,
            False,
            1,
        )
    )

    assert cloned == {"vmid": 151, "node": "pve1"}
    assert migrated == {"node": "pve2", "status": "stopped"}
    assert moved == {"disk": "scsi0", "storage": "local"}
    commands = repository.connection.commands
    assert any("INSERT INTO resources" in command for command in commands)
    assert any("node_id=$2" in command for command in commands)
