"""Identity, vocabulary, region scope, and presence/eligibility separation tests."""

from __future__ import annotations

import pytest
from sqlalchemy import Connection, text
from sqlalchemy.exc import DBAPIError, IntegrityError

from conftest import add_observation, add_snapshot


@pytest.mark.database
@pytest.mark.integration
def test_osm_identity_types_ids_and_region_scope(db: Connection, seed: dict[str, int]) -> None:
    del seed
    db.execute(
        text(
            "INSERT INTO osm_lead_source.osm_source_object (osm_type, osm_id) "
            "VALUES ('way', 123), ('relation', 123)"
        )
    )
    db.execute(
        text(
            "INSERT INTO osm_lead_source.source_region "
            "(region_id, display_name, extract_name) VALUES ('other-region', 'Other', 'other')"
        )
    )
    snapshot = add_snapshot(db, region="other-region", age_days=1)
    add_observation(db, snapshot, 123, "way")
    add_observation(db, snapshot, 123, "relation")
    with pytest.raises(DBAPIError):
        with db.begin_nested():
            db.execute(
                text(
                    "INSERT INTO osm_lead_source.osm_source_object (osm_type, osm_id) "
                    "VALUES ('area', 1)"
                )
            )
    with pytest.raises(DBAPIError):
        with db.begin_nested():
            db.execute(
                text(
                    "INSERT INTO osm_lead_source.osm_source_object (osm_type, osm_id) "
                    "VALUES ('node', 0)"
                )
            )


@pytest.mark.database
@pytest.mark.integration
def test_composite_snapshot_region_references_reject_cross_region_rows(
    db: Connection, seed: dict[str, int]
) -> None:
    add_observation(db, seed["snapshot"])
    db.execute(
        text(
            "INSERT INTO osm_lead_source.source_region "
            "(region_id, display_name, extract_name) VALUES ('other-region', 'Other', 'other')"
        )
    )
    other_snapshot = add_snapshot(db, region="other-region", age_days=1)
    with pytest.raises(DBAPIError):
        with db.begin_nested():
            db.execute(
                text(
                    "INSERT INTO osm_lead_source.osm_source_presence "
                    "(region_id, osm_type, osm_id, source_presence_state, latest_snapshot_id, "
                    "completeness_status) VALUES ('test-region', 'node', 123, 'present', :snapshot, 'complete')"
                ),
                {"snapshot": other_snapshot},
            )


@pytest.mark.database
@pytest.mark.integration
def test_eligibility_is_separate_and_cross_region_snapshot_is_rejected(
    db: Connection, seed: dict[str, int]
) -> None:
    add_observation(db, seed["snapshot"])
    db.execute(
        text(
            "INSERT INTO osm_lead_source.osm_source_presence "
            "(region_id, osm_type, osm_id, source_presence_state, latest_snapshot_id, "
            "completeness_status) VALUES ('test-region', 'node', 123, 'present', :snapshot, 'complete')"
        ),
        seed,
    )
    db.execute(
        text(
            "INSERT INTO osm_lead_source.profile_version "
            "(profile_id, profile_version, lifecycle_state) VALUES "
            "('profile-a', '1', 'draft'), ('profile-b', '1', 'draft')"
        )
    )
    for profile, state in (("profile-a", "active"), ("profile-b", "out_of_scope")):
        db.execute(
            text(
                "INSERT INTO osm_lead_source.osm_profile_eligibility "
                "(region_id, osm_type, osm_id, profile_id, profile_version, eligibility_state, "
                "source_snapshot_id) VALUES ('test-region', 'node', 123, :profile, '1', :state, :snapshot)"
            ),
            {"profile": profile, "state": state, "snapshot": seed["snapshot"]},
        )
    assert (
        db.execute(
            text("SELECT source_presence_state FROM osm_lead_source.osm_source_presence")
        ).scalar_one()
        == "present"
    )

    db.execute(
        text(
            "INSERT INTO osm_lead_source.source_region "
            "(region_id, display_name, extract_name) VALUES ('other-region', 'Other', 'other')"
        )
    )
    other_snapshot = add_snapshot(db, region="other-region", age_days=1)
    with pytest.raises(IntegrityError):
        with db.begin_nested():
            db.execute(
                text(
                    "UPDATE osm_lead_source.osm_profile_eligibility SET source_snapshot_id = :snapshot "
                    "WHERE region_id = 'test-region' AND osm_type = 'node' AND osm_id = 123 "
                    "AND profile_id = 'profile-b' AND profile_version = '1'"
                ),
                {"snapshot": other_snapshot},
            )

    with pytest.raises(IntegrityError):
        with db.begin_nested():
            db.execute(
                text(
                    "INSERT INTO osm_lead_source.reconciliation_run "
                    "(region_id, source_snapshot_id, code_version, configuration_hash) "
                    "VALUES ('test-region', :snapshot, 'test', :hash)"
                ),
                {"snapshot": other_snapshot, "hash": "a" * 64},
            )
    db.execute(
        text(
            "UPDATE osm_lead_source.osm_profile_eligibility SET eligibility_state = 'excluded' "
            "WHERE profile_id = 'profile-a'"
        )
    )
    assert (
        db.execute(
            text("SELECT source_presence_state FROM osm_lead_source.osm_source_presence")
        ).scalar_one()
        == "present"
    )
