"""Tests for DbtAdapter — manifest resolution and ref() parsing."""
import json

import pytest

from kanoniv.adapters.dbt import DbtAdapter, _strip_ref


class TestStripRef:
    def test_single_quoted_ref(self):
        assert _strip_ref("ref('stg_orders')") == "stg_orders"

    def test_double_quoted_ref(self):
        assert _strip_ref('ref("stg_orders")') == "stg_orders"

    def test_bare_name(self):
        assert _strip_ref("stg_orders") == "stg_orders"

    def test_ref_with_spaces(self):
        assert _strip_ref("ref( 'stg_orders' )") == "stg_orders"


class TestDbtAdapter:
    @pytest.fixture
    def manifest_path(self, tmp_path):
        manifest = {
            "nodes": {
                "model.project.stg_orders": {
                    "resource_type": "model",
                    "name": "stg_orders",
                    "database": "analytics_db",
                    "schema": "staging",
                    "alias": "stg_orders",
                    "columns": {
                        "order_id": {"name": "order_id", "data_type": "integer"},
                        "customer_email": {"name": "customer_email", "data_type": "string"},
                        "total": {"name": "total", "data_type": "number"},
                    },
                },
                "model.project.dim_customers": {
                    "resource_type": "model",
                    "name": "dim_customers",
                    "database": "analytics_db",
                    "schema": "marts",
                    "alias": None,
                    "columns": {},
                },
                "source.project.raw_orders": {
                    "resource_type": "source",
                    "name": "raw_orders",
                    "database": "raw",
                    "schema": "public",
                },
            }
        }
        p = tmp_path / "manifest.json"
        p.write_text(json.dumps(manifest))
        return str(p)

    def test_manifest_model_resolution(self, manifest_path):
        adapter = DbtAdapter("stg_orders", manifest_path=manifest_path)
        table = adapter._resolve_table()
        assert table == "analytics_db.staging.stg_orders"

    def test_ref_syntax_resolution(self, manifest_path):
        adapter = DbtAdapter("ref('stg_orders')", manifest_path=manifest_path)
        table = adapter._resolve_table()
        assert table == "analytics_db.staging.stg_orders"

    def test_double_quoted_ref_resolution(self, manifest_path):
        adapter = DbtAdapter('ref("stg_orders")', manifest_path=manifest_path)
        table = adapter._resolve_table()
        assert table == "analytics_db.staging.stg_orders"

    def test_model_not_found(self, manifest_path):
        adapter = DbtAdapter("nonexistent_model", manifest_path=manifest_path)
        with pytest.raises(ValueError, match="not found"):
            adapter._resolve_table()

    def test_schema_from_manifest_columns(self, manifest_path):
        adapter = DbtAdapter("stg_orders", manifest_path=manifest_path)
        schema = adapter.schema()
        assert len(schema.columns) == 3
        col_names = {c.name for c in schema.columns}
        assert "order_id" in col_names
        assert "customer_email" in col_names

    def test_alias_none_uses_name(self, manifest_path):
        adapter = DbtAdapter("dim_customers", manifest_path=manifest_path)
        table = adapter._resolve_table()
        assert table == "analytics_db.marts.dim_customers"

    def test_ignores_non_model_nodes(self, manifest_path):
        """Source nodes should not be matched as models."""
        adapter = DbtAdapter("raw_orders", manifest_path=manifest_path)
        with pytest.raises(ValueError, match="not found"):
            adapter._resolve_table()
