#
# Copyright (c) Daniel Sheffield 2023
#
# All rights reserved
#
# THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
from typing import Dict, Iterable, Tuple
from pandas import DataFrame
from pytest import fixture, mark
from app.rest.form import get_option_groups

@fixture
def data():
    return DataFrame({
        'type': ['dog', 'cat', 'horse', 'sheep', 'cow'],
        'category': ['pet', 'pet', 'utility', 'farm', 'farm'],
        'group': ['small', 'small', 'large', 'medium', 'large',],
        'tags': [['a'], ['a','b'], [], [], []],
        '$/unit': ['1', '2', '3', '4', '5'],
    })

@mark.parametrize('filter_data, _type, key, parent_grouping, expected', [
    ({
        'type': [{'dog'}, {'cat'}]
    }, 'include', 'type', 'category', [
        {
            "optgroup": 'pet', "options": [{
                "selected": True,
                "value": "dog",
                "display": "dog",
            }]
        }, {
            "optgroup": None, "options":[{
                "selected": False,
                "value": "cat",
                "display": "cat",
            }]
        }
    ]), ({
        'type': [{'dog'}, {'cat'}]
    }, 'exclude', 'type', 'category', [
        {
            "optgroup": 'pet', "options": [{
                "selected": False,
                "value": "!dog",
                "display": "dog",
            }],
        }, {
            "optgroup": None, "options":[{
                "selected": True,
                "value": "!cat",
                "display": "cat",
            }],
        }
    ]), ({
        'group': [{'small'}, {'large'}]
    }, 'include', 'group', None, [
        {
            "optgroup": None, "options": [ {
                "selected": False,
                "value": "large",
                "display": "large",
            },{
                "selected": True,
                "value": "small",
                "display": "small",
            }],
        }
    ]), ({
        'group': [{'small'}, {'large'}]
    }, 'exclude', 'group', None, [
        {
            "optgroup": None, "options": [{
                "selected": True,
                "value": "!large",
                "display": "large",
            },{
                "selected": False,
                "value": "!small",
                "display": "small",
            }],
        }
    ]),  ({
        'tag': [{'a'}, {'b'}]
    }, 'include', 'tag', None, [
        {
            "optgroup": None, "options": [ {
                "selected": True,
                "value": "a",
                "display": "a",
            },{
                "selected": False,
                "value": "b",
                "display": "b",
            }],
        }
    ]), ({
        'tag': [{'a'}, {'b'}]
    }, 'exclude', 'tag', None, [
        {
            "optgroup": None, "options": [{
                "selected": False,
                "value": "!a",
                "display": "a",
            },{
                "selected": True,
                "value": "!b",
                "display": "b",
            }],
        }
    ]),
])
def test_get_option_groups(
    data: DataFrame,  _type: str,
    filter_data: Dict[str, Tuple[set, set]],
    key: str, parent_grouping: str,
    expected: Iterable
):

    _filter = data['type'].apply(lambda _: False)
    for k, (inc, exc) in filter_data.items():
        for i in inc:
            _filter |= (data['tags'].apply(lambda x: i in x) if k == 'tag' else data[k] == i)
        for i in exc:
            _filter &= ~(data['tags'].apply(lambda x: i in x) if k == 'tag' else data[k] == i)
    assert list(get_option_groups(data[_filter], filter_data, key, parent_grouping, _type)) == expected