from __future__ import annotations

import pytest

from sync_state_machine.common.collection import DataCollection
from sync_state_machine.datasource.datasource import BaseDataSource
from sync_state_machine.datasource.handler import ValidationResult
from sync_state_machine.datasource.task_result import TaskResult


class _FailHandler:
    @property
    def node_type(self) -> str:
        return "fail"

    @property
    def node_class(self):
        return None

    @property
    def schema(self):
        return None

    def set_collection(self, collection) -> None:
        self._collection = collection

    async def load(self):
        raise RuntimeError("boom")

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

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

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

    async def poll_tasks(self, task_ids):
        return {}

    async def validate(self, data):
        return ValidationResult(is_valid=True)

    def extract_id(self, data):
        return ""

    def _create_node(self, data):
        return None


class _OkHandler:
    @property
    def node_type(self) -> str:
        return "ok"

    @property
    def node_class(self):
        return None

    @property
    def schema(self):
        return None

    def set_collection(self, collection) -> None:
        self._collection = collection

    async def load(self):
        return []

    async def create_all(self, nodes):
        return [TaskResult.success(node_id=str(i), data_id=str(i)) for i, _ in enumerate(nodes)]

    async def update_all(self, nodes):
        return [TaskResult.success(node_id=str(i), data_id=str(i)) for i, _ in enumerate(nodes)]

    async def delete_all(self, nodes):
        return [TaskResult.success(node_id=str(i), data_id=str(i)) for i, _ in enumerate(nodes)]

    async def poll_tasks(self, task_ids):
        return {}

    async def validate(self, data):
        return ValidationResult(is_valid=True)

    def extract_id(self, data):
        return ""

    def _create_node(self, data):
        return None


class _DS(BaseDataSource):
    pass


@pytest.mark.asyncio
async def test_load_all_continue_when_one_handler_fails(capsys) -> None:
    ds = _DS()
    ds.add_handler(_FailHandler())
    ds.add_handler(_OkHandler())
    ds.set_collection(DataCollection("local"))

    await ds.load_all(order=["fail", "ok"])

    out = capsys.readouterr().out
    assert "[fail] 加载失败" in out
    assert "Loaded nodes for ok: 0" in out
