import pytest


@pytest.mark.parametrize(
	["raw", "mapping", "expected"],
	[
		pytest.param(*p[1:], id=p[0])
		for p in [
			[
				"flat dictionary",
				{"a": 1, "b": 2},
				{"a": "alpha", "b": "beta"},
				{"alpha": 1, "beta": 2},
			],
			[
				"flat list",
				[1, 2, 3],
				["a", "b", "c"],
				{"a": 1, "b": 2, "c": 3},
			],
			[
				"flat list not matching length",
				[1, 2, 3],
				["a", "b"],
				{"a": 1, "b": 2},
			],
			[
				"flat tuple",
				(1, 2, 3),
				["a", "b", "c"],
				{"a": 1, "b": 2, "c": 3},
			],
			[
				"nested structures",
				{"a": 1, "b": {"c": 2}, "d": [3, 4]},
				{"a": "alpha", "b": {"c": "gamma"}, "d": ["delta", "epsilon"]},
				{"alpha": 1, "gamma": 2, "delta": 3, "epsilon": 4},
			],
			[
				"nested structures with additional values",
				{"a": 1, "b": {"c": 2, "d": 3}, "d": [3, 4, 6], "e": 5},
				{"a": "alpha", "b": {"c": "gamma"}, "d": ["delta", "epsilon"]},
				{"alpha": 1, "gamma": 2, "delta": 3, "epsilon": 4},
			],
		]
	],
)
def test_positive(raw, mapping, expected):
	from ai_parade._toolkit.structural_mapping import structural_map

	result = structural_map(raw, mapping)
	assert result == expected


@pytest.mark.parametrize(
	["raw", "mapping", "expected"],
	[
		pytest.param(*p[1:], id=p[0])
		for p in [
			[
				"skipping in a list",
				[1, 2, 3, 4, 5, 6],
				[
					"a",
					"...skip",
					"c",
					"...skip",
					"e",
				],
				{"a": 1, "c": 3, "e": 5},
			],
			[
				"repeating patterns (single value)",
				[1, 2, 3, 4, 5, 6],
				["a", "...repeat"],
				{"a": [1, 2, 3, 4, 5, 6]},
			],
			[
				"repeating patterns (single value, no input)",
				[],
				["a", "...repeat"],
				{"a": []},
			],
			[
				"repeating patterns (single value, 1 repetition)",
				[1],
				["a", "...repeat"],
				{"a": [1]},
			],
			[
				"repeating patterns (multiple values, no input)",
				[],
				["odd", "even", "...repeat"],
				{"odd": [], "even": []},
			],
			[
				"repeating patterns (multiple values, partial input)",
				[1],
				["odd", "even", "...repeat"],
				{"odd": [1], "even": []},
			],
			[
				"repeating patterns (multiple values)",
				[1, 2, 3, 4, 5, 6],
				["odd", "even", "...repeat"],
				{"odd": [1, 3, 5], "even": [2, 4, 6]},
			],
			[
				"repeating patterns (multiple values, 1 repetition)",
				[1, 2],
				["odd", "even", "...repeat"],
				{"odd": [1], "even": [2]},
			],
			[
				"repeating patterns with skipping",
				[1, 2, 3, 4, 5, 6],
				["odd", "even", "...skip", "...repeat"],
				{"odd": [1, 4], "even": [2, 5]},
			],
			[
				"named repeating patterns (no input)",
				[],
				["a", "b", "...skip", "...repeat as group"],
				{"group": []},
			],
			[
				"named repeating patterns",
				[1, 2, 3, 4, 5, 6],
				["a", "b", "...skip", "...repeat as group"],
				{"group": [{"a": 1, "b": 2}, {"a": 4, "b": 5}]},
			],
			[
				"named repeating patterns (merge)",
				{"a_values": [1, 2], "b_values": [3, 4]},
				{
					"a_values": ["a", "...repeat as group"],
					"b_values": ["b", "...repeat as group"],
				},
				{"group": [{"a": 1, "b": 3}, {"a": 2, "b": 4}]},
			],
			[
				"nested named repeating patterns",
				[{"a": [1, 2, 3, 4, 5, 6]}, {"a": [7, 8, 9, 10, 11, 12]}],
				[
					{"a": ["alpha", "beta", "...skip", "...repeat as inner_group"]},
					"...repeat as outer_group",
				],
				{
					"outer_group": [
						{
							"inner_group": [
								{"alpha": 1, "beta": 2},
								{"alpha": 4, "beta": 5},
							]
						},
						{
							"inner_group": [
								{"alpha": 7, "beta": 8},
								{"alpha": 10, "beta": 11},
							]
						},
					]
				},
			],
		]
	],
)
def test_special_symbols(raw, mapping, expected):
	from ai_parade._toolkit.structural_mapping import structural_map

	result = structural_map(raw, mapping)
	assert result == expected


@pytest.mark.parametrize(
	["raw", "mapping"],
	[
		pytest.param(*p[1:], id=p[0])
		for p in [
			[
				"missing dict key",
				{"a": 1},
				{"a": "alpha", "b": "beta"},
			],
			[
				"missing tuple index",
				[1, 2],
				["a", "b", "c"],
			],
			[
				"missing nested dict key",
				{"a": 1, "b": {"c": 2}},
				{"a": "alpha", "b": {"c": "gamma", "d": "delta"}},
			],
			[
				"missing nested tuple index",
				{"a": [1, 2], "b": 3},
				{"a": ["alpha", "beta", "gamma"], "b": "delta"},
			],
			[
				"empty dict with mapping",
				{},
				{"a": "alpha", "b": "beta"},
			],
			[
				"empty list with tuple mapping",
				[],
				["a", "b"],
			],
			[
				"nested repeating patterns",
				[{"group": [1, 2, 3, 4, 5, 6]}, {"group": [7, 8, 9, 10, 11, 12]}],
				[{"group": ["odd", "even", "...repeat"]}, "...repeat"],
			],
			[
				"nested repeating patterns (inner named)",
				[{"group": [1, 2, 3, 4, 5, 6]}, {"group": [7, 8, 9, 10, 11, 12]}],
				[{"group": ["a", "b", "...skip", "...repeat as group"]}, "...repeat"],
			],
			[
				"named repeating patterns - input not divisible",
				[1, 2],
				["a", "b", "...skip", "...repeat as group"],
			],
		]
	],
)
def test_negative_missing_symbols(raw, mapping):
	from ai_parade._toolkit.structural_mapping import (
		StructuralMappingError,
		structural_map,
	)

	with pytest.raises(StructuralMappingError):
		structural_map(raw, mapping)
