from __future__ import annotations

from typing import Any

from pydantic import BaseModel

from sync_state_machine.common.sync_node import SyncNode
from sync_state_machine.datasource.api.handler import BaseApiHandler
from sync_state_machine.datasource.handler import BaseNodeHandler, CompatibleNodeHandler
from sync_state_machine.datasource.task_result import TaskResult


class SharedConfigSchema(BaseModel):
    __test__ = False
    id: str


class SharedConfigNode(SyncNode[SharedConfigSchema]):
    __test__ = False
    node_type = "shared_config_demo"
    schema = SharedConfigSchema


class SharedConfigBaseHandler(BaseNodeHandler[SharedConfigSchema]):
    __test__ = False

    def __init__(self) -> None:
        super().__init__("shared_config_demo", SharedConfigNode, SharedConfigSchema)

    async def load(self):
        return []

    async def create_all(self, nodes):
        return []

    async def update_all(self, nodes):
        return []

    def extract_id(self, data: dict[str, Any]) -> str:
        return str(data.get("id", ""))


class SharedConfigApiHandler(BaseApiHandler[SharedConfigSchema]):
    __test__ = False

    def __init__(self) -> None:
        super().__init__()
        self._node_type = "shared_api_demo"
        self._node_class = SharedConfigNode
        self._schema = SharedConfigSchema

    async def load(self):
        return []

    async def create_all(self, nodes):
        return [TaskResult.success(node_id=node.node_id) for node in nodes]

    async def update_all(self, nodes):
        return [TaskResult.success(node_id=node.node_id) for node in nodes]

    async def delete_all(self, nodes):
        return [TaskResult.success(node_id=node.node_id) for node in nodes]


def test_base_handler_supports_shared_handler_config() -> None:
    handler = SharedConfigBaseHandler()

    handler.set_handler_config({"mode": "local", "batch_size": 10})

    assert handler.handler_config == {"mode": "local", "batch_size": 10}


def test_compatible_handler_forwards_shared_handler_config() -> None:
    handler = CompatibleNodeHandler(SharedConfigBaseHandler())

    handler.set_handler_config({"mode": "remote"})

    assert handler.handler_config == {"mode": "remote"}


def test_api_handler_supports_shared_handler_config() -> None:
    handler = SharedConfigApiHandler()

    handler.set_handler_config({"filter_project_id": ["p1", "p2"]})

    assert handler.handler_config == {"filter_project_id": ["p1", "p2"]}
