from __future__ import annotations

from types import SimpleNamespace

import pytest

from sync_state_machine.sync_system.resolve_ids import IDResolver


class FakeNode:
    def __init__(self, *, node_id: str, node_type: str, data_id: str, data: dict[str, object]):
        self.node_id = node_id
        self.node_type = node_type
        self.data_id = data_id
        self._data = data

    def get_data(self):
        return self._data

    def set_data(self, data):
        self._data = data


class FakeCollection:
    def __init__(self, nodes: list[FakeNode]):
        self._by_node_id = {node.node_id: node for node in nodes}
        self._by_data_id = {node.data_id: node for node in nodes}

    def get_by_data_id(self, node_type: str, data_id: str):
        del node_type
        return self._by_data_id.get(data_id)

    def get_by_data_id_any(self, data_id: str):
        return self._by_data_id.get(data_id)

    def get(self, node_id: str):
        return self._by_node_id.get(node_id)


class FakeBindingManager:
    def __init__(self, mapping: dict[str, str]):
        self._mapping = mapping

    async def get_local_id(self, node_type: str, remote_node_id: str):
        del node_type
        return self._mapping.get(remote_node_id)


@pytest.mark.asyncio
async def test_resolve_and_validate_replaces_list_dependency_fields(monkeypatch):
    remote_nodes = [
        FakeNode(node_id="remote-project-node-1", node_type="project", data_id="remote-project-1", data={}),
        FakeNode(node_id="remote-project-node-2", node_type="project", data_id="remote-project-2", data={}),
    ]
    local_nodes = [
        FakeNode(node_id="local-project-node-1", node_type="project", data_id="local-project-1", data={}),
        FakeNode(node_id="local-project-node-2", node_type="project", data_id="local-project-2", data={}),
    ]

    remote_collection = FakeCollection(remote_nodes)
    local_collection = FakeCollection(local_nodes)
    binding_manager = FakeBindingManager(
        {
            "remote-project-node-1": "local-project-node-1",
            "remote-project-node-2": "local-project-node-2",
        }
    )

    class TempNode:
        def __init__(self, node_id: str, data_id: str, data: dict[str, object]):
            self.node_id = node_id
            self.data_id = data_id
            self._data = data

        def get_data(self):
            return self._data

        def set_data(self, data):
            self._data = data

    monkeypatch.setattr("sync_state_machine.common.registry.DomainRegistry.get_node_class", lambda node_type: TempNode)

    resolver = IDResolver(local_collection, remote_collection, binding_manager)
    resolved_data, error = await resolver.resolve_and_validate(
        data={"project_ids": ["remote-project-1", "remote-project-2"], "name": "demo"},
        node_type="user",
        depend_fields={"project_ids": "project"},
        to_remote=False,
    )

    assert error is None
    assert resolved_data is not None
    assert resolved_data["project_ids"] == ["local-project-1", "local-project-2"]
    assert resolved_data["name"] == "demo"