"""
Test for header cleaning
========================

**Module:** ``tests.test_clean_headers``
"""

from typing import List, Optional, Type

import pytest

from _ptcsvp.parametrize import clean_headers
from pytest_csv_params.exception import CsvHeaderNameInvalid
from pytest_csv_params.types import HeaderRenames


@pytest.mark.parametrize(
    ["current_headers", "replacing", "expect_exception", "expect_message", "expect_result"],
    [
        (
            ["alpha 3", "_beta_5", "Ga Mm A"],
            None,
            None,
            None,
            ["alpha_3", "_beta_5", "Ga_Mm_A"],
        ),
        (
            ["abcd" * 300, "_be:ta_ :23", "Ra -/2"],
            None,
            CsvHeaderNameInvalid,
            f"'{'abcd' * 300}' is not a valid variable name",
            None,
        ),
        (
            ["next_var", "_be:ta_ :23", "Ra -/2"],
            None,
            None,
            None,
            ["next_var", "_be_ta___23", "Ra___2"],
        ),
        (
            ["next_var", "_be:ta_ :23", "Ra -/2", "Ra___2"],
            None,
            CsvHeaderNameInvalid,
            "Header names are not unique",
            None,
        ),
        (
            ["next_var", "_be:ta_ :23", "Ra -/2"],
            {"Ra -/2": "ra", "not here": "not_here"},
            None,
            None,
            ["next_var", "_be_ta___23", "ra"],
        ),
        (
            ["next", "_be:ta_ :23", "Ra -/2"],
            None,
            CsvHeaderNameInvalid,
            "'next' is not a valid variable name",
            None,
        ),
    ],
)
def test_header_cleaning(
    current_headers: List[str],
    replacing: HeaderRenames,
    expect_exception: Optional[Type[ValueError]],
    expect_message: Optional[str],
    expect_result: List[str],
) -> None:
    """
    This test case tests mainly the :meth:`_ptcsvp.parametrize.clean_headers` method.

    There are many single test cases built with parametrization.

    :param current_headers: List of headers before cleaning
    :param replacing: A replacement dictionary
    :param expect_exception: Exception to expect during method call
    :param expect_message: Exception message to be expected
    :param expect_result: Expected cleaned headers
    """
    if expect_exception is not None:
        with pytest.raises(expect_exception) as raised_error:
            clean_headers(current_headers, replacing)
        assert raised_error.value.args[0] == expect_message
    else:
        result = clean_headers(current_headers, replacing)
        assert result == expect_result
