"""Tests for PayerConfig277CA loading from YAML.

SP10 T4. Mirrors ``test_payer_config_loading.py`` but for the new
``PayerConfig277CA`` block that the 277CA parser and Inbox lane
consume for status-code classification.
"""
from __future__ import annotations

from pathlib import Path

import pytest
import yaml

from cyclone.payers import (
    DEFAULT_CONFIG_PATH,
    _tx_to_model,
    all_configs,
    get_config,
    load_payer_configs,
    reset,
)
from cyclone.providers import PayerConfig277CA


@pytest.fixture(autouse=True)
def _clear_registry():
    """Each test starts with an empty config registry."""
    reset()
    yield
    reset()


class TestPayerConfig277CALoading:
    def test_loads_default_config_with_277ca_block(self):
        """The default config/payers.yaml must have a CO_TXIX 277CA block."""
        load_payer_configs(DEFAULT_CONFIG_PATH)
        cfg = get_config("CO_TXIX", "277CA")
        assert cfg is not None
        # Defaults from PayerConfig277CA.
        assert "A6" in cfg["rejected_status_codes"]
        assert "A8" in cfg["pended_status_codes"]
        assert "A3" in cfg["accepted_status_codes"]
        assert "P1" in cfg["paid_status_codes"]
        assert "277CA" in cfg["transaction_set_ids_allowed"]

    def test_model_rejects_bad_status_code_type(self, tmp_path: Path):
        """A non-list rejected_status_codes value must fail validation."""
        bad = {
            "payers": [
                {
                    "payer_id": "BAD_PAYER",
                    "name": "Bad",
                    "receiver_name": "BAD",
                    "receiver_id": "BADID",
                    "configs": {
                        "277CA": {
                            "rejected_status_codes": "A6",  # must be list
                            "pended_status_codes": ["A8"],
                            "accepted_status_codes": ["A1"],
                            "paid_status_codes": ["P1"],
                            "transaction_set_ids_allowed": ["277", "277CA"],
                            "implementation_guide": "005010X214",
                        },
                    },
                },
            ],
        }
        p = tmp_path / "bad.yaml"
        p.write_text(yaml.safe_dump(bad))
        with pytest.raises(ValueError, match="BAD_PAYER"):
            load_payer_configs(p)


class TestPayerConfig277CAModel:
    def test_default_factory_values(self):
        """A minimal PayerConfig277CA defaults to the canonical HCPF sets."""
        cfg = PayerConfig277CA()
        assert "A4" in cfg.rejected_status_codes
        assert "A6" in cfg.rejected_status_codes
        assert "A7" in cfg.rejected_status_codes
        assert "A8" in cfg.pended_status_codes
        assert "277CA" in cfg.transaction_set_ids_allowed

    def test_explicit_override(self):
        cfg = PayerConfig277CA(
            rejected_status_codes=["X1"],
            pended_status_codes=["X2"],
            accepted_status_codes=["X3"],
            paid_status_codes=["X4"],
        )
        assert cfg.rejected_status_codes == ["X1"]
        assert cfg.pended_status_codes == ["X2"]


class TestTxToModelFor277CA:
    def test_int_key_routes_to_277ca_model(self):
        """PyYAML may parse numeric keys as int — _tx_to_model must handle both."""
        # 277CA as int isn't likely (not pure digits), but 277 as int is.
        # Test the canonical string.
        assert _tx_to_model("277CA") is PayerConfig277CA

    def test_string_key_routes_correctly(self):
        assert _tx_to_model("277CA") is PayerConfig277CA
        assert _tx_to_model("835") is not PayerConfig277CA  # it's 835 model
