import pandas as pd

from fmatch.core import engine


def test_should_not_skip_reasonable_large_match_block() -> None:
    should_skip = engine._should_skip_block(
        "exa",
        num_src=9999,
        num_ref=2000,
        max_size=engine.MAX_BLOCK_SIZE,
        max_ops=engine.MAX_BLOCK_OPERATIONS,
        is_dedup=False,
    )
    assert should_skip is False


def test_process_block_shards_with_mapped_name_columns(monkeypatch) -> None:
    src = pd.DataFrame(
        {
            "source_id": [f"s{i}" for i in range(6000)],
            "company": [f"Acme {i % 50}" for i in range(6000)],
            "website_domain": ["example.com"] * 6000,
        }
    )
    ref = pd.DataFrame(
        {
            "reference_id": [f"r{i}" for i in range(2000)],
            "Name": [f"Acme {i % 50}" for i in range(2000)],
            "Website": ["example.com"] * 2000,
        }
    )

    seen_block_keys = []

    def _fake_large(*args, **kwargs):
        # Signature: (src_block_df, ref_block_df, block_key_val, ...)
        seen_block_keys.append(args[2])
        return []

    monkeypatch.setattr(engine, "process_large_block_cdist", _fake_large)
    monkeypatch.setattr(engine, "process_small_block_tuples", lambda *a, **k: [])

    result = engine.process_block(
        src_block_df=src,
        ref_block_df=ref,
        block_key_val="exa",
        block_idx=0,
        src_id_col="source_id",
        ref_id_col="reference_id",
        threshold=0.8,
        algo_key_str="WRatio",
        maps_for_algo=[{"source": "company", "reference": "Name", "weight": 1.0}],
        enable_multi_algo=False,
        scorer=None,
        enhanced_mappings=[],
        algo_callable=lambda *_: 100,
        coverage_gate=0.0,
        MAX_TOTAL_WEIGHT=1.0,
        pid=1,
    )

    assert result == []
    assert seen_block_keys
    assert all(str(key).startswith("exa_") for key in seen_block_keys)


def test_process_block_falls_back_when_shard_keys_do_not_overlap(monkeypatch) -> None:
    src = pd.DataFrame(
        {
            "source_id": [f"s{i}" for i in range(6000)],
            "company_name": [f"sourcecompany{i}" for i in range(6000)],
            "website_domain": ["example.com"] * 6000,
        }
    )
    ref = pd.DataFrame(
        {
            "reference_id": [f"r{i}" for i in range(2000)],
            "company_name": [f"targetcompany{i}" for i in range(2000)],
            "Website": ["example.com"] * 2000,
        }
    )

    seen_block_keys = []

    def _fake_large(*args, **kwargs):
        seen_block_keys.append(args[2])
        return []

    monkeypatch.setattr(engine, "process_large_block_cdist", _fake_large)
    monkeypatch.setattr(engine, "process_small_block_tuples", lambda *a, **k: [])

    result = engine.process_block(
        src_block_df=src,
        ref_block_df=ref,
        block_key_val="exa",
        block_idx=0,
        src_id_col="source_id",
        ref_id_col="reference_id",
        threshold=0.8,
        algo_key_str="WRatio",
        maps_for_algo=[{"source": "company_name", "reference": "company_name", "weight": 1.0}],
        enable_multi_algo=False,
        scorer=None,
        enhanced_mappings=[],
        algo_callable=lambda *_: 100,
        coverage_gate=0.0,
        MAX_TOTAL_WEIGHT=1.0,
        pid=1,
    )

    assert result == []
    assert seen_block_keys == ["exa_fallback"]
