from __future__ import annotations

from cognite_data_quality._records import RecordsConfig, Violation, build_records, parse_focus_node_uri


def test_parse_focus_node_uri_simple() -> None:
    """Simple format: namespace_base + space + '/' + external_id (no 'space/' prefix)."""
    base = "http://purl.org/cognite/"
    assert parse_focus_node_uri(f"{base}sp/inst1", base) == ("sp", "inst1")
    assert parse_focus_node_uri(f"{base}mySpace/someExternalId", base) == ("mySpace", "someExternalId")


def test_parse_focus_node_uri_neat_format() -> None:
    """Neat format: namespace_base + 'space/' + instance_space + '#' + urlencoded(external_id)."""
    base = "http://purl.org/cognite/"
    uri = f"{base}space/sailboat#boat%3A%3A257553460"
    assert parse_focus_node_uri(uri, base) == ("sailboat", "boat::257553460")
    assert parse_focus_node_uri(f"{base}space/mySpace#id%2Fwith%2Fslashes", base) == (
        "mySpace",
        "id/with/slashes",
    )


def test_parse_focus_node_uri_invalid() -> None:
    base = "http://purl.org/cognite/"
    assert parse_focus_node_uri("", base) is None
    assert parse_focus_node_uri("http://other/space/x", base) is None
    assert parse_focus_node_uri(f"{base}space/no_hash", base) is None


def test_build_records_with_violation() -> None:
    instances = [{"space": "sp", "externalId": "inst1"}]
    violations = [
        Violation(
            focusNode="http://purl.org/cognite/sp/inst1",
            resultMessage="Missing field",
            resultSeverity="Violation",
            sourceConstraintComponent="sh:MaxCountConstraintComponent",
            resultPath="prop",
        )
    ]
    records_config = RecordsConfig(rule_set_id="Set", rule_set_version="1.0")

    items = build_records(
        instances,
        violations,
        job_run_id="job1",
        records_config=records_config,
        namespace_base="http://purl.org/cognite/",
    )

    assert len(items) == 1
    properties = items[0]["sources"][0]["properties"]
    assert properties["ruleSetId"] == "Set"
    assert properties["failedConstraints"]


def test_build_records_with_warning_severity() -> None:
    instances = [{"space": "sp", "externalId": "inst1"}]
    violations = [
        Violation(
            focusNode="http://purl.org/cognite/sp/inst1",
            resultMessage="Warning message",
            resultSeverity="http://www.w3.org/ns/shacl#Warning",
            sourceConstraintComponent="sh:MaxCountConstraintComponent",
        )
    ]
    records_config = RecordsConfig(rule_set_id="Set", rule_set_version="1.0")

    items = build_records(
        instances,
        violations,
        job_run_id="job1",
        records_config=records_config,
        namespace_base="http://purl.org/cognite/",
    )

    properties = items[0]["sources"][0]["properties"]
    assert properties["resultSeverity"] == ["Warning"]


def test_build_records_without_violations() -> None:
    instances = [{"space": "sp", "externalId": "inst1"}]
    records_config = RecordsConfig(rule_set_id="Set", rule_set_version="1.0")

    items = build_records(
        instances,
        [],
        job_run_id="job1",
        records_config=records_config,
        namespace_base="http://purl.org/cognite/",
    )

    properties = items[0]["sources"][0]["properties"]
    assert properties["passedValidation"] is True
    assert properties["validationReport"]["violationCount"] == 0


def test_build_records_neat_format_focus_node() -> None:
    """Violations with neat-format focusNode match instances by (space, externalId)."""
    instances = [{"space": "sailboat", "externalId": "boat::257553460"}]
    violations = [
        Violation(
            focusNode="http://purl.org/cognite/space/sailboat#boat%3A%3A257553460",
            resultMessage="Missing field",
            resultSeverity="Violation",
            sourceConstraintComponent="sh:MaxCountConstraintComponent",
        )
    ]
    records_config = RecordsConfig(rule_set_id="Set", rule_set_version="1.0")

    items = build_records(
        instances,
        violations,
        job_run_id="job1",
        records_config=records_config,
        namespace_base="http://purl.org/cognite/",
    )

    assert len(items) == 1
    properties = items[0]["sources"][0]["properties"]
    assert properties["focusNodeInstance"] == {"space": "sailboat", "externalId": "boat::257553460"}
    assert properties["failedConstraints"]
    assert not properties["passedValidation"]
