"""
第二期数据库基线服务测试
"""

from contextlib import nullcontext

from services.phase2_baseline_service import Phase2BaselineService


def test_build_sql_plan_should_return_idempotent_sql_plan_for_selected_phase2_baselines():
    """抽中第二期基线规则时，应生成幂等 SQL 计划。"""
    service = Phase2BaselineService()

    sql_plan = service.build_sql_plan(
        staff_id_card="330101198801010011",
        family_id_cards=["330101199001010022"],
        baseline_rule_codes=[
            "SUPPLIER_CONCENTRATION",
            "HOUSE_REGISTRATION_MISMATCH",
        ],
    )

    assert any("LSFXMOCKP2PUR001" in sql for sql in sql_plan)
    assert any("LSFX Mock P2 HOUSE" in sql for sql in sql_plan)
    assert any("'房产'" in sql for sql in sql_plan)
    assert any("'正常'" in sql for sql in sql_plan)
    assert any(sql.strip().startswith("DELETE") for sql in sql_plan)
    assert any(sql.strip().startswith("INSERT") for sql in sql_plan)


def test_build_sql_plan_should_skip_unselected_phase2_rules():
    """未选中的规则不应写入无关 SQL。"""
    service = Phase2BaselineService()

    sql_plan = service.build_sql_plan(
        staff_id_card="330101198801010011",
        family_id_cards=[],
        baseline_rule_codes=["SUPPLIER_CONCENTRATION"],
    )

    assert any("LSFXMOCKP2PUR001" in sql for sql in sql_plan)
    assert not any("LSFX Mock P2 HOUSE" in sql for sql in sql_plan)
    assert not any("ccdi_asset_info" in sql for sql in sql_plan)


def test_build_sql_plan_should_include_low_income_family_baseline():
    """低收入亲属大额交易需要额外补齐关系表收入基线。"""
    service = Phase2BaselineService()

    sql_plan = service.build_sql_plan(
        staff_id_card="330101198801010011",
        family_id_cards=["330101199001010022"],
        baseline_rule_codes=["LOW_INCOME_RELATIVE_LARGE_TRANSACTION"],
    )

    assert any("ccdi_staff_fmy_relation" in sql for sql in sql_plan)
    assert any("'330101198801010011'" in sql for sql in sql_plan)
    assert any("'330101199001010022'" in sql for sql in sql_plan)
    assert any("annual_income" in sql for sql in sql_plan)
    assert any("0.00" in sql or "0," in sql or " 0\n" in sql for sql in sql_plan)


def test_build_sql_plan_should_use_staff_scope_for_family_asset_baselines():
    """亲属资产基线应保留员工归属与亲属实际持有人的双字段语义。"""
    service = Phase2BaselineService()

    sql_plan = service.build_sql_plan(
        staff_id_card="330101198801010011",
        family_id_cards=["330101199001010022"],
        baseline_rule_codes=["PROPERTY_FEE_REGISTRATION_MISMATCH"],
    )

    assert any("'330101198801010011'" in sql for sql in sql_plan)
    assert any("'330101199001010022'" in sql for sql in sql_plan)
    assert not any("'REAL_ESTATE'" in sql for sql in sql_plan)


def test_apply_should_execute_generated_sql_plan(monkeypatch):
    """apply() 应执行生成出的 SQL 计划，而不是只返回字符串。"""
    service = Phase2BaselineService()
    executed_sql = []
    committed = {"value": False}

    class FakeCursor:
        def execute(self, sql):
            executed_sql.append(sql.strip())

    class FakeConnection:
        def __init__(self):
            self.cursor_instance = FakeCursor()

        def cursor(self):
            return nullcontext(self.cursor_instance)

        def commit(self):
            committed["value"] = True

        def rollback(self):
            raise AssertionError("测试路径不应触发回滚")

        def __enter__(self):
            return self

        def __exit__(self, exc_type, exc, tb):
            return False

    monkeypatch.setattr(service, "_connect", lambda: FakeConnection())

    result = service.apply(
        staff_id_card="330101198801010011",
        family_id_cards=["330101199001010022"],
        baseline_rule_codes=["SUPPLIER_CONCENTRATION"],
    )

    assert result is None
    assert committed["value"] is True
    assert any("DELETE FROM ccdi_purchase_transaction" in sql for sql in executed_sql)
    assert any("INSERT INTO ccdi_purchase_transaction" in sql for sql in executed_sql)


def test_apply_should_execute_low_income_family_baseline_sql(monkeypatch):
    """apply() 在低收入亲属规则下应执行关系表基线 SQL。"""
    service = Phase2BaselineService()
    executed_sql = []

    class FakeCursor:
        def execute(self, sql):
            executed_sql.append(sql.strip())

    class FakeConnection:
        def __init__(self):
            self.cursor_instance = FakeCursor()

        def cursor(self):
            return nullcontext(self.cursor_instance)

        def commit(self):
            return None

        def rollback(self):
            raise AssertionError("测试路径不应触发回滚")

        def __enter__(self):
            return self

        def __exit__(self, exc_type, exc, tb):
            return False

    monkeypatch.setattr(service, "_connect", lambda: FakeConnection())

    service.apply(
        staff_id_card="330101198801010011",
        family_id_cards=["330101199001010022"],
        baseline_rule_codes=["LOW_INCOME_RELATIVE_LARGE_TRANSACTION"],
    )

    assert any("ccdi_staff_fmy_relation" in sql for sql in executed_sql)
    assert any("annual_income" in sql for sql in executed_sql)
