"""Persistent LXC semantic handler tests."""

import uuid
from datetime import UTC, datetime
from typing import Any

import pytest
from fastapi import Request

from app.api.errors import ApiError
from app.api.registry import HandlerRegistry
from app.handlers.lxc import register_lxc_handlers


class LxcPool:
    def __init__(self) -> None:
        self.resource_exists = False
        self.missing = False
        self.running = False
        self.commands: list[str] = []
        self.resource_id = uuid.uuid4()

    async def fetchval(self, sql: str, *args: object) -> bool | int:
        del args
        if "pg_backend_pid" in sql:
            return 123
        if "extract(epoch" in sql:
            return 1_700_000_000
        if "FROM nodes" in sql:
            return True
        if "FROM resources" in sql:
            return self.resource_exists
        if "FROM snapshots" in sql:
            return False
        raise AssertionError(sql)

    async def fetch(self, sql: str, *args: object) -> list[dict[str, object]]:
        del args
        if "FROM resources" in sql and "kind='lxc'" in sql:
            return [
                {
                    "vmid": 200,
                    "state": '{"status":"stopped","name":"service"}',
                    "config": '{"hostname":"service","memory":512,"cores":1}',
                }
            ]
        assert "FROM snapshots" in sql
        return [
            {
                "name": "baseline",
                "parent_name": None,
                "description": "stable",
                "created_at": datetime(2026, 1, 1, tzinfo=UTC),
            }
        ]

    async def fetchrow(self, sql: str, *args: object) -> dict[str, object] | None:
        del args
        if self.missing:
            return None
        if "SELECT r.id, r.version" in sql:
            return {
                "id": self.resource_id,
                "version": 1,
                "state": '{"name":"old","status":"stopped"}',
                "config": '{"name":"old"}',
            }
        if "SELECT r.id, r.state, c.config" in sql:
            return {"id": self.resource_id, "state": '{"status":"stopped"}', "config": "{}"}
        if "SELECT r.id, r.state FROM resources" in sql:
            status = "running" if self.running else "stopped"
            return {"id": self.resource_id, "state": f'{{"status":"{status}"}}'}
        if "SELECT s.* FROM snapshots" in sql:
            return {
                "id": uuid.uuid4(),
                "name": "baseline",
                "parent_name": None,
                "description": "stable",
                "created_at": datetime(2026, 1, 1, tzinfo=UTC),
                "state": "{}",
            }
        raise AssertionError(sql)

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


class FakeDatabase:
    def __init__(self, pool: LxcPool) -> None:
        self.pool = pool


class FakeTaskRepository:
    def __init__(self, pool: LxcPool) -> None:
        self.pool = pool
        self.created: list[dict[str, Any]] = []

    async def create(self, **kwargs: Any) -> Any:
        self.created.append(kwargs)
        return type(
            "Task", (), {"upid": "UPID:pve1:00000001:00000001:1700000000:pctcreate:201:root@pam:"}
        )()


def _request(pool: LxcPool) -> Request:
    app = type("App", (), {"state": type("State", (), {"database": FakeDatabase(pool)})()})()
    request = Request({"type": "http", "headers": [], "method": "POST", "path": "/"})
    request.scope["app"] = app
    request.state.principal = "root@pam"
    return request


@pytest.fixture
def registry() -> HandlerRegistry:
    handler_registry = HandlerRegistry()
    register_lxc_handlers(handler_registry)
    return handler_registry


async def test_lxc_list_returns_seeded_containers(registry: HandlerRegistry) -> None:
    pool = LxcPool()
    handler = registry.get("/nodes/{node}/lxc", "GET")
    assert handler is not None
    result = await handler(_request(pool), {"values": {"node": "pve1"}})
    assert len(result) == 1
    assert result[0]["vmid"] == 200
    assert result[0]["status"] == "stopped"
    assert result[0]["name"] == "service"
    assert result[0]["cpus"] == 1
    assert "maxmem" in result[0]


async def test_lxc_create_rejects_duplicate_vmid(registry: HandlerRegistry) -> None:
    pool = LxcPool()
    pool.resource_exists = True
    handler = registry.get("/nodes/{node}/lxc", "POST")
    assert handler is not None
    with pytest.raises(ApiError, match="VMID already exists"):
        await handler(
            _request(pool),
            {"values": {"node": "pve1", "vmid": 201, "hostname": "app"}},
        )


async def test_lxc_delete_requires_stopped_container(registry: HandlerRegistry) -> None:
    pool = LxcPool()
    pool.running = True
    handler = registry.get("/nodes/{node}/lxc/{vmid}", "DELETE")
    assert handler is not None
    with pytest.raises(ApiError, match="cannot delete a running container"):
        await handler(_request(pool), {"values": {"node": "pve1", "vmid": "200"}})


async def test_lxc_start_creates_task(
    monkeypatch: pytest.MonkeyPatch, registry: HandlerRegistry
) -> None:
    pool = LxcPool()
    repository = FakeTaskRepository(pool)
    monkeypatch.setattr("app.handlers.lxc.TaskRepository", lambda _pool: repository)
    handler = registry.get("/nodes/{node}/lxc/{vmid}/status/start", "POST")
    assert handler is not None
    upid = await handler(_request(pool), {"values": {"node": "pve1", "vmid": "200"}})
    assert upid.startswith("UPID:")
    assert repository.created[0]["task_type"] == "lxc-start"
