"""
Test for the internal parametrization feature
=============================================

**Module:** ``tests.test_parametrize``
"""

from os.path import dirname, join
from typing import List, Optional, Tuple, Type

import pytest

from _ptcsvp.parametrize import add_parametrization
from pytest_csv_params.exception import CsvParamsDataFileInvalid, CsvParamsDataFileNotFound


@pytest.mark.parametrize(
    ["csv_file", "id_col", "result", "ids", "expect_exception", "expect_message"],
    [
        ("test0", "#ID", None, None, CsvParamsDataFileNotFound, None),
        (
            "test1",
            "#ID",
            (
                ["Animal", "Color"],
                [
                    ["Cat", "Blue"],
                    ["Dog", "Green"],
                    ["Mouse", "Yellow"],
                    ["Bird", "Purple"],
                    ["Cow", "Red"],
                ],
            ),
            ["A1", "A2", "A3", "A4", "A5"],
            None,
            None,
        ),
        ("test2", "#ID", None, None, CsvParamsDataFileInvalid, "Header and Data length mismatch"),
        ("test3", "#ID", None, None, CsvParamsDataFileInvalid, "Header and Data length mismatch"),
        ("test4", "#ID", None, None, CsvParamsDataFileInvalid, "Invalid data"),
        ("test5", "#ID", None, None, CsvParamsDataFileInvalid, "Header and Data length mismatch"),
        ("test6", "#ID", None, None, CsvParamsDataFileInvalid, "Cannot find ID column '#ID'"),
        ("test7", "#ID", None, None, CsvParamsDataFileInvalid, "File does not contain a single data row"),
        ("test8", "#ID", None, None, CsvParamsDataFileInvalid, "File does not contain a single data row"),
        ("test9", "#ID", None, None, CsvParamsDataFileInvalid, "File seems only to have IDs"),
        ("test0", "#ID", None, None, CsvParamsDataFileNotFound, None),
        (
            "test10",
            "#ID",
            (
                ["Animal", "Color"],
                [
                    ["Cat", "Blue"],
                    ["Dog", "Green"],
                    ["Mouse", "Yellow"],
                    ["Bird", "Purple"],
                    ["Cow", "Red"],
                    ["Rat", "Black"],
                ],
            ),
            ["A1", "A2", "A3", "A4", "A5", "A7"],
            None,
            None,
        ),
        (
            "test11",
            None,
            (
                ["Animal", "Color"],
                [
                    ["Cat", "Blue"],
                    ["Dog", "Green"],
                    ["Mouse", "Yellow"],
                    ["Bird", "Purple"],
                    ["Cow", "Red"],
                ],
            ),
            None,
            None,
            None,
        ),
    ],
)
def test_parametrization(  # pylint: disable=too-many-arguments
    csv_file: str,
    id_col: Optional[str],
    result: Optional[Tuple[List[str], List[List[str]]]],
    ids: Optional[List[str]],
    expect_exception: Optional[Type[Exception]],
    expect_message: Optional[str],
) -> None:
    """
    This test case tests mainly the internal :meth:`_ptcsvp.parametrize.add_parametrization` method, which is the
    backbone of the public :meth:`~pytest_csv_params.decorator.csv_params` decorator.

    The test is heavily parametrized. See source code for detail.

    :param csv_file: CSV file for the test
    :param id_col: The ID column name of the CSV file
    :param result: Expected result, as it would be handed over to the :meth:`pytest.mark.parametrize` mark decorator
    :param ids: Expected test case IDs
    :param expect_exception: Expected exception during call
    :param expect_message: Expected exception message during call
    """
    data_file = join(dirname(__file__), "assets", f"{csv_file}.csv")
    if expect_exception:
        with pytest.raises(expect_exception) as raised_exception:
            add_parametrization(data_file=data_file, id_col=id_col, data_casts={"Number": int})
        if expect_message is not None:
            assert raised_exception.value.args[0] == expect_message
    else:
        parameterization = add_parametrization(data_file=data_file, id_col=id_col, data_casts={"Number": int})
        assert parameterization is not None
        assert isinstance(parameterization, type(pytest.mark.parametrize))
        assert parameterization.mark.args == parameterization.args
        assert parameterization.args == result
        assert parameterization.kwargs.get("ids", None) == ids
