"""Tests for template_generator module, specifically RAW SHACL generation functions."""

from cognite.client.data_classes import Row
from cognite_data_quality.template_generator import _analyze_raw_schema, _generate_raw_shacl_from_schema


def test_analyze_raw_schema():
    """Test RAW schema analysis."""
    rows = [
        Row(key="1", columns={"a": "foo", "b": 123, "c": None}),
        Row(key="2", columns={"a": "bar", "b": 456}),
        Row(key="3", columns={"a": "baz", "b": 789, "c": "value"}),
    ]

    schema, row_count = _analyze_raw_schema(rows)

    assert row_count == 3
    assert len(schema) == 3
    assert schema["a"]["type"] == "string"
    assert schema["a"]["present_in"] == 3  # In all rows
    assert schema["b"]["type"] == "int"
    assert schema["b"]["present_in"] == 3  # In all rows
    assert schema["c"]["type"] == "string"
    assert schema["c"]["present_in"] == 2  # In 2 out of 3 rows
    assert schema["c"]["nullable"] is True


def test_generate_raw_shacl_percentage_calculation():
    """Test that column presence percentages are calculated correctly (bug fix verification)."""
    schema = {
        "always_present": {"type": "string", "present_in": 100, "nullable": False},
        "mostly_present": {"type": "int", "present_in": 75, "nullable": False},
        "rarely_present": {"type": "string", "present_in": 25, "nullable": True},
    }

    shacl_rules = _generate_raw_shacl_from_schema(
        db_name="test_db",
        table_name="test_table",
        schema=schema,
        row_count=100,  # 100 rows sampled
        required_columns=None,
    )

    # Verify percentage comments are correct (bug fix)
    assert "Present in: 100% of rows" in shacl_rules  # always_present
    assert "Present in: 75% of rows" in shacl_rules  # mostly_present
    assert "Present in: 25% of rows" in shacl_rules  # rarely_present

    # Before the fix, all would have shown 33% (each present_in / 3 columns * 100)
    assert "Present in: 33% of rows" not in shacl_rules


def test_generate_raw_shacl_edge_cases():
    """Test edge cases for percentage calculation."""

    # Edge case: Single row
    schema = {"col1": {"type": "string", "present_in": 1, "nullable": False}}
    shacl_rules = _generate_raw_shacl_from_schema("db", "table", schema, row_count=1, required_columns=None)
    assert "Present in: 100% of rows" in shacl_rules

    # Edge case: Very sparse column (1 out of 1000 rows = 0.1%)
    schema = {"sparse": {"type": "string", "present_in": 1, "nullable": True}}
    shacl_rules = _generate_raw_shacl_from_schema("db", "table", schema, row_count=1000, required_columns=None)
    assert "Present in: 0% of rows" in shacl_rules  # Rounds down


def test_generate_raw_shacl_required_columns():
    """Test that required columns generate sh:minCount constraints."""
    schema = {
        "required_col": {"type": "string", "present_in": 100, "nullable": False},
        "optional_col": {"type": "int", "present_in": 50, "nullable": True},
    }

    shacl_rules = _generate_raw_shacl_from_schema(
        db_name="test_db",
        table_name="test_table",
        schema=schema,
        row_count=100,
        required_columns=["required_col"],
    )

    # Check that required column has minCount
    assert "sh:minCount 1" in shacl_rules
    assert 'sh:message "required_col is required"' in shacl_rules


def test_generate_raw_shacl_type_constraints():
    """Test that type constraints are generated correctly."""
    schema = {
        "string_col": {"type": "string", "present_in": 10, "nullable": False},
        "int_col": {"type": "int", "present_in": 10, "nullable": False},
        "float_col": {"type": "float", "present_in": 10, "nullable": False},
        "bool_col": {"type": "boolean", "present_in": 10, "nullable": False},
    }

    shacl_rules = _generate_raw_shacl_from_schema(
        db_name="test_db",
        table_name="test_table",
        schema=schema,
        row_count=10,
        required_columns=None,
    )

    # Check XSD type mappings
    assert "xsd:string" in shacl_rules
    assert "xsd:integer" in shacl_rules
    assert "xsd:double" in shacl_rules
    assert "xsd:boolean" in shacl_rules


def test_analyze_raw_schema_type_inference():
    """Test that type inference handles mixed types correctly."""
    rows = [
        Row(key="1", columns={"mixed": "string"}),
        Row(key="2", columns={"mixed": 123}),  # Mixed with int - should become string
        Row(key="3", columns={"pure_int": 456}),
        Row(key="4", columns={"pure_int": 789}),
    ]

    schema, _row_count = _analyze_raw_schema(rows)

    # Mixed types should fallback to string
    assert schema["mixed"]["type"] == "string"
    assert schema["mixed"]["present_in"] == 2

    # Pure int should stay int
    assert schema["pure_int"]["type"] == "int"
    assert schema["pure_int"]["present_in"] == 2
