import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))


def test_base_class_is_importable():
    from scripts.integrations.base import IntegrationBase
    assert IntegrationBase is not None


def test_base_class_is_abstract():
    from scripts.integrations.base import IntegrationBase
    import inspect
    assert inspect.isabstract(IntegrationBase)


def test_registry_is_importable():
    from scripts.integrations import REGISTRY
    assert isinstance(REGISTRY, dict)


def test_registry_returns_integration_base_subclasses():
    """Any entries in the registry must be IntegrationBase subclasses."""
    from scripts.integrations import REGISTRY
    from scripts.integrations.base import IntegrationBase
    for name, cls in REGISTRY.items():
        assert issubclass(cls, IntegrationBase), f"{name} is not an IntegrationBase subclass"


def test_base_class_has_required_class_attributes():
    """Subclasses must define name, label, tier at the class level."""
    from scripts.integrations.base import IntegrationBase

    class ConcreteIntegration(IntegrationBase):
        name = "test"
        label = "Test Integration"
        tier = "free"

        def fields(self): return []
        def connect(self, config): return True
        def test(self): return True

    instance = ConcreteIntegration()
    assert instance.name == "test"
    assert instance.label == "Test Integration"
    assert instance.tier == "free"


def test_fields_returns_list_of_dicts():
    """fields() must return a list of dicts with key, label, type."""
    from scripts.integrations.base import IntegrationBase

    class TestIntegration(IntegrationBase):
        name = "test2"
        label = "Test 2"
        tier = "free"

        def fields(self):
            return [{"key": "token", "label": "API Token", "type": "password",
                     "placeholder": "abc", "required": True, "help": ""}]

        def connect(self, config): return bool(config.get("token"))
        def test(self): return True

    inst = TestIntegration()
    result = inst.fields()
    assert isinstance(result, list)
    assert len(result) == 1
    assert result[0]["key"] == "token"


def test_save_and_load_config(tmp_path):
    """save_config writes yaml; load_config reads it back."""
    from scripts.integrations.base import IntegrationBase

    class TestIntegration(IntegrationBase):
        name = "savetest"
        label = "Save Test"
        tier = "free"
        def fields(self): return []
        def connect(self, config): return True
        def test(self): return True

    inst = TestIntegration()
    config = {"token": "abc123", "database_id": "xyz"}
    inst.save_config(config, tmp_path)

    saved_file = tmp_path / "integrations" / "savetest.yaml"
    assert saved_file.exists()

    loaded = inst.load_config(tmp_path)
    assert loaded["token"] == "abc123"
    assert loaded["database_id"] == "xyz"


def test_is_configured(tmp_path):
    from scripts.integrations.base import IntegrationBase

    class TestIntegration(IntegrationBase):
        name = "cfgtest"
        label = "Cfg Test"
        tier = "free"
        def fields(self): return []
        def connect(self, config): return True
        def test(self): return True

    assert TestIntegration.is_configured(tmp_path) is False
    # Create the file
    (tmp_path / "integrations").mkdir(parents=True)
    (tmp_path / "integrations" / "cfgtest.yaml").write_text("token: x\n")
    assert TestIntegration.is_configured(tmp_path) is True


def test_sync_default_returns_zero():
    from scripts.integrations.base import IntegrationBase

    class TestIntegration(IntegrationBase):
        name = "synctest"
        label = "Sync Test"
        tier = "free"
        def fields(self): return []
        def connect(self, config): return True
        def test(self): return True

    inst = TestIntegration()
    assert inst.sync([]) == 0
    assert inst.sync([{"id": 1}]) == 0


def test_registry_has_all_13_integrations():
    """After all modules are implemented, registry should have 13 entries."""
    from scripts.integrations import REGISTRY
    expected = {
        "notion", "google_drive", "google_sheets", "airtable",
        "dropbox", "onedrive", "mega", "nextcloud",
        "google_calendar", "apple_calendar",
        "slack", "discord", "home_assistant",
    }
    assert expected == set(REGISTRY.keys()), (
        f"Missing: {expected - set(REGISTRY.keys())}, "
        f"Extra: {set(REGISTRY.keys()) - expected}"
    )


def test_all_integrations_have_required_attributes():
    from scripts.integrations import REGISTRY
    for name, cls in REGISTRY.items():
        assert hasattr(cls, "name") and cls.name, f"{name} missing .name"
        assert hasattr(cls, "label") and cls.label, f"{name} missing .label"
        assert hasattr(cls, "tier") and cls.tier in ("free", "paid", "premium"), f"{name} invalid .tier"


def test_all_integrations_fields_schema():
    from scripts.integrations import REGISTRY
    for name, cls in REGISTRY.items():
        inst = cls()
        fields = inst.fields()
        assert isinstance(fields, list), f"{name}.fields() must return list"
        for f in fields:
            assert "key" in f, f"{name} field missing 'key'"
            assert "label" in f, f"{name} field missing 'label'"
            assert "type" in f, f"{name} field missing 'type'"
            assert f["type"] in ("text", "password", "url", "checkbox"), \
                f"{name} field type must be text/password/url/checkbox"


def test_free_integrations():
    from scripts.integrations import REGISTRY
    free_integrations = {"google_drive", "dropbox", "onedrive", "mega", "nextcloud", "discord", "home_assistant"}
    for name in free_integrations:
        assert name in REGISTRY, f"{name} not in registry"
        assert REGISTRY[name].tier == "free", f"{name} should be tier='free'"


def test_paid_integrations():
    from scripts.integrations import REGISTRY
    paid_integrations = {"notion", "google_sheets", "airtable", "google_calendar", "apple_calendar", "slack"}
    for name in paid_integrations:
        assert name in REGISTRY, f"{name} not in registry"
        assert REGISTRY[name].tier == "paid", f"{name} should be tier='paid'"
